Do not use a Mutable object as the default value of a function
Copy Code code as follows:
In [1]: def append_to_list (value, def_list=[]):
...: def_list.append (value)
...: Return Def_list
...:
In [2]: My_list = append_to_list (1)
In [3]: My_list
OUT[3]: [1]
In [4]: My_other_list = append_to_list (2)
In [5]: My_other_list
OUT[5]: [1, 2] # See, actually we were just trying to generate [2] but it brought in the first-run effect page.
In [6]: Import time
In [7]: def report_arg (My_default=time.time ()):
...: print (My_default)
...:
In [8]: Report_arg () # First time execution
1399562371.32
In [9]: Time.sleep (2) # 2 seconds apart
In [ten]: Report_arg ()
1399562371.32 # time has not changed
What do these 2 examples illustrate? Dictionaries, collections, lists, and so on are objects that are not suitable as default values for functions. Because this default value is generated when the function is established, each call is made with the "cache" of this object. I shared Python advanced programming in the last part of the issue, this is the actual development of the problems encountered, check the code you have learned, perhaps only the problem is not exposed
You can change this:
Copy Code code as follows:
def append_to_list (element, To=none):
If to is None:
to = []
To.append (Element)
Return to
Second, the generator does not preserve the results after the iteration
Copy Code code as follows:
in [[]: Gen = (I for I in range (5))
in [+]: 2 in Gen
OUT[13]: True
In [%]: 3 in Gen
OUT[14]: True
in [[): 1 in Gen
OUT[15]: False # 1 Why not in Gen? Because the call to 1->2, this time 1 is not in the iterator, has been generated on demand
In [m]: gen = (I for I in range (5))
in [[]: A_list = list (gen) # can be converted into lists, of course a_tuple = tuple (gen) can also
in [[): 2 in A_list
OUT[22]: True
In [%]: 3 in A_list
OUT[23]: True
In [$]: 1 in A_list # even if the cycle, the value is still
OUT[24]: True
Three, the lambda in the closure will save the local variables
Copy Code code as follows:
In [to]: My_list = [lambda:i for I in range (5)]
in [/]: for L in My_list:
...: Print (L ())
....:
4
4
4
4
4
This question is also mentioned above in the Python advanced programming in the specific reasons. In fact, when I assign a value to my_list, the lambda expression executes I loops until I =4,i retains
But you can use the generator
Copy Code code as follows:
In [to]: My_gen = (lambda:n for n in range (5))
In [£]: for L in My_gen:
...: Print (L ())
....:
0
1
2
3
4
You can also stick with list:
Copy Code code as follows:
In [m]: my_list = [Lambda x=i:x for I in range (5)] # Look, I assigned a default value to each lambda expression
In [%]: for L in My_list:
...: Print (L ())
....:
0
1
2
3
4
It's a little hard to understand, isn't it, looking at another Python magic:
Copy Code code as follows:
in [[]: Def groupby (items, size):
...: Return Zip (*[iter (items)]*size)
....:
in [[]: GroupBy (Range (9), 3)
OUT[36]: [(0, 1, 2), (3, 4, 5), (6, 7, 8)]
A grouped function that doesn't look good, does it? Let's parse this down here.
Copy Code code as follows:
in [[]: [ITER (items)]*3
OUT[39]:
[<listiterator at 0x10e155fd0>
<listiterator at 0x10e155fd0>
<listiterator at 0x10e155fd0>] # see, in fact, is to turn items into iterations, repeat three times (the same object OH), but don't forget, every time. Next (), so it plays a role in grouping
in [/]: [Lambda x=i:x for-I in range (5)]
OUT[40]:
[<function __main__.<lambda>>
<function __main__.<lambda>>
<function __main__.<lambda>>
<function __main__.<lambda>>
<function __main__.<lambda>>] # can you understand?
Modify the list item in the Loop
Copy Code code as follows:
in [[]: A = [1, 2, 3, 4, 5]
in [/]: For I in a:
...: If not I% 2:
...: A.remove (i)
....:
in [+]: A
OUT[46]: [1, 3, 5] # no problem
In [$]: b = [2, 4, 5, 6]
In [Wuyi]: For i in B:
...: If not I% 2:
...: B.remove (i)
....:
In [$]: b
OUT[52]: [4, 5] # The result I wanted would have been to remove the even list
Think about it, why-it's because your remove to the list affects its index
Copy Code code as follows:
In [%]: b = [2, 4, 5, 6]
In [i]: for index, item in enumerate (b):
...: Print (index, item)
...: If not item% 2:
...: B.remove (item)
....:
(0, 2) # There's no problem. 2 was deleted.
(1, 5) # because 2 was deleted the current list is [4, 5, 6], so the index list[1] goes directly to the 5, ignoring the 4
(2, 6)
V. Indexerror-List value exceeded his index number
Copy Code code as follows:
In [$]: My_list = [1, 2, 3, 4, 5]
In [to]: my_list[5] # There's no such element at all
---------------------------------------------------------------------------
Indexerror Traceback (most recent call last)
<ipython-input-56-037d00de8360> in <module> ()
----> 1 my_list[5]
Indexerror:list index out of range # throw an exception
In [$]: my_list[5:] # But you can do this, you must pay attention to, with good is trick, with the wrong is the pit AH
OUT[57]: []
Vi. Reuse of global variables
Copy Code code as follows:
In [%]: def my_func ():
...: Print (VAR) # I can call an undefined variable first
....:
in [[]: var = ' Global ' # after assignment
In [$]: My_func () # Anyway, as long as you call the function, the variable is defined.
Global
In [%]: def my_func ():
...: var = ' locally changed '
....:
in [+]: var = ' global '
in [[]: My_func ()
In [£]: print (VAR)
Global # Local variable has no effect on globally variable
In [$]: def my_func ():
...: Print (VAR) # Although you set this variable globally, but local variables have the same name, Python thinks you forgot to define the local variables.
...: var = ' locally changed '
....:
In [$]: var = ' global '
In [to]: My_func ()
---------------------------------------------------------------------------
Unboundlocalerror Traceback (most recent call last)
<ipython-input-67-d82eda95de40> in <module> ()
----> 1 My_func ()
<ipython-input-65-0ad11d690936> in My_func ()
1 def my_func ():
----> 2 print (VAR)
3 var = ' locally changed '
4
Unboundlocalerror:local variable ' var ' referenced before assignment
In [to]: Def my_func ():
...: Global Var # This is the time to add to the picture.
...: Print (VAR) # So you can use it properly.
...: var = ' locally changed '
....:
In [on]: var = ' global '
In [70]:
In [to]: My_func ()
Global
In [under]: print (VAR)
Locally changed # But with global it changed the variables
VII. copy of Variable objects
Copy Code code as follows:
in [[a]: My_list1 = [[1, 2, 3]] * 2
In [My_list1]:
OUT[73]: [[1, 2, 3], [1, 2, 3]]
in [[]: my_list1[1][0] = ' A ' # I only modify one of the child lists
In [$]: My_list1
OUT[75]: [[' A ', 2, 3], [' A ', 2, 3]] # but it all affects
In ["]: My_list2 = [[1, 2, 3] for I in range (2)] # The method of generating different objects in this loop does not affect
In [more]: my_list2[1][0] = ' a '
In [My_list2]:
OUT[78]: [[1, 2, 3], [' A ', 2, 3]]
Viii. python multiple Inheritance (C3)
Copy Code code as follows:
In [1]: Class A (object):
...: def foo (self):
...: Print ("Class A")
...:
In [2]: Class B (object):
...: def foo (self):
...: Print ("Class B")
...:
In [3]: Class C (A, B):
..: Pass
...:
In [4]: C (). Foo ()
Class A # example is very understood, C inherited A and B, from left to right, found a has Foo method, returned the
It all seems very simple, orderly from the bottom up, looking backwards in the past, find and return. Look again at the example:
Copy Code code as follows:
In [5]: Class A (object):
...: def foo (self):
...: Print ("Class A")
...:
In [6]: Class B (A):
..: Pass
...:
In [7]: Class C (A):
...: def foo (self):
...: Print ("Class C")
...:
In [8]: Class D (B,C):
..: Pass
...:
In [9]: D (). Foo ()
Class C #? According to the truth, the order is d->b->a, why did you find C?
This also involves MRO (method resolution Order):
Copy Code code as follows:
In [ten]: d.__mro__
OUT[10]: (__main__. D, __main__. B, __main__. C, __main__. A, Object)
The simple understanding is actually the new class is the breadth first, d->b, but discovers the C also inherits a, first finds the C, finally then goes to find a
Ix. List of + and + =, append and Extend
Copy Code code as follows:
in [[]: Print (' ID: ', ID (a_list))
(' ID: ', 4481323592)
in [[a]: A_list + = [1]
in [[]: Print (' id (+ =): ', ID (a_list))
(' ID (+ = =: ', 4481323592) # using + + or on the original list
In [m]: a_list = A_list + [2]
in [[]: Print (' id (list = list + ...): ', ID (a_list))
(' ID (list = list + ...): ', 4481293056] # simple + actually has changed the original list
in [[]: A_list = []
In [to]: ID (a_list)
OUT[29]: 4481326976
In [m]: a_list.append (1)
In [to]: ID (a_list)
OUT[31]: 4481326976 # Append is added in the original list
In [O]: A_list.extend ([2])
in [+]: ID (a_list)
OUT[33]: 4481326976 # Extend is also added on the original list
Ten, DateTime also has a Boolean value
It's a pit.
Copy Code code as follows:
In [%]: import datetime
in [[]: Print (' Datetime.time (0,0,0) "(midnight)-> ', BOOL (Datetime.time (0,0,0)))
(' Datetime.time (0,0,0) ' (midnight)-> ', False)
in [[]: Print (' Datetime.time (1,0,0) "(1 am)-> ', BOOL (Datetime.time (1,0,0)))
(' Datetime.time (1,0,0) ' (1 am)-> ', True)
Xi. difference between ' = = ' and is
My understanding is that ' is ' is to judge the identity of 2 objects, = = To determine the value of 2 objects
Copy Code code as follows:
In [Panax]: a = 1
in [[]: b = 1
in [[]: Print (' A are B ', bool (A is B))
(' A is B ', True)
in [/]: c = 999
In [a]: D = 999
in [[]: Print (' C are d ', BOOL (c is D))
(' C is d ', False) # The reason is Python's memory management, Cache-5-256 objects
In [%]: print (' 256 is 257-1 ', 256 is 257-1)
(' 256 is 257-1 ', True)
in [[]: Print (' 257 are 258-1 ', 257 is 258-1)
(' 257 is 258-1 ', False)
in [[]: Print ('-5 is-6+1 ',-5 is-6+1)
('-5 is-6+1 ', True)
in [[]: Print ('-7 is-6-1 ',-7 is-6-1)
('-7 is-6-1 ', False)
In [$]: a = ' Hello world! '
in [+]: b = ' Hello world! '
in [[]: Print (' A are B, ', A is B)
(' A is B, ', False) # Obviously they're not cached, this is an object of 2 field strings
In [x]: Print (' A = = B, ', a = = b)
(' A = = B, ', True ') # But their values are the same
# But, there's a special case
In [Wuyi]: a = float (' nan ')
In [i]: print (' A is a, ', ' a ', ')
(' A is a, ', True)
In [%]: print (' a = = A, ', a = = a)
(' A = = A, ', False) # Blinded my eyes ~
12, shallow copy and deep copy
In actual development, we can make changes to objects in a list, but we may not want to change the original list. A shallow copy copies only the parent object, and a deep copy also copies the inner child objects of the object
Copy Code code as follows:
In [$]: List1 = [1, 2]
In [$]: List2 = list1 # is a reference, you operate list2, in fact, list1 results will change
in [[]: List3 = list1[:]
In [to]: import copy
In [m]: List4 = Copy.copy (list1) # He's a light copy like List3.
In [to]: ID (LIST1), id (LIST2), id (LIST3), ID (LIST4)
OUT[71]: (4480620232, 4480620232, 4479667880, 4494894720)
in [[]: list2[0] = 3
In [the]: print (' List1: ', List1)
(' List1: ', [3, 2])
in [[]: list3[0] = 4
in [[]: list4[1] = 4
in [[]: Print (' List1: ', List1)
(' List1: ', [3, 2]) # LIST3 and LIST4 operations have no effect on List1
# and look at the difference between a deep copy and a shallow copy
in [+]: From copy import copy, deepcopy
In [$]: List1 = [[1], [2]]
In [s]: List2 = Copy (list1) # or shallow copy
In [$]: List3 = Deepcopy (list1) # deep copy
In [$]: ID (LIST1), id (LIST2), ID (LIST3)
OUT[92]: (4494896592, 4495349160, 4494896088)
In [$]: list2[0][0] = 3
In [to]: print (' List1: ', List1)
(' List1: ', [[3], [2]]] # See, if you manipulate its child objects or the same as a reference, it affects the source.
In []: list3[0][0] = 5
In [to]: print (' List1: ', List1)
(' List1: ', [[3], [2]]) # Deep copy will not affect
13, BOOL is actually a subclass of int
Copy Code code as follows:
In [Isinstance]: (True, int)
OUT[97]: True
in [+]: true + True
OUT[98]: 2
In [$]: 3 * true + True
OUT[99]: 4
In [m]: 3 * true-false
OUT[100]: 3
in [[]: True << 10
OUT[104]: 1024
Is the META group really immutable?
Copy Code code as follows:
in [[]: Tup = ([],)
in [112]: tup[0] = [1]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-112-d4f292cf35de> in <module> ()
----> 1 tup[0] + = [1]
TypeError: ' Tuple ' object does not support item assignment
In [113]: Tup
OUT[113]: ([1],) # I'm blinded by my eyes, I can still change the exception
In [114]: Tup = ([],)
In [Tup[0].extend]: ([1])
In [116]: tup[0]
OUT[116]: [1] # Well, I kind of see, though I can't manipulate tuples directly, but I can't stop me from manipulating variable child objects in tuples (list)
Well, here's a nice explanation. Python ' s + = Weird, part II:
Copy Code code as follows:
In [117]: My_tup = (1,)
In [118]: My_tup = (4,)
In [119]: My_tup = My_tup + (5,)
In [My_tup]:
OUT[120]: (1, 4, 5) #? Well, isn't it possible to manipulate tuples?
In [121]: My_tup = (1,)
In [122]: Print (ID (my_tup))
4481317904
In [123]: My_tup = (4,)
In [124]: Print (ID (my_tup))
4480606864 # operation is not the original tuple so you can
in [[]: My_tup = My_tup + (5,)
In [126]: Print (ID (my_tup))
4474234912
16. Python has no private method/variable? But there can be "false"
Copy Code code as follows:
In [127]: Class My_class (Object^e):
...: def public_method (self):
...: print (' Hello public world! ')
...: def __private_method (self): # Private starts with double underlines
...: print (' Hello private world! ')
...: def call_private_method_in_class (self):
.....: Self.__private_method ()
In [132]: My_instance = My_class ()
In [My_instance.public_method]: ()
Hello Public world! # Common method
In [134]: My_instance._my_class__private_method ()
Hello Private world! # private can add "_ + Class name + Private method name"
In [135]: My_instance.call_private_method_in_class ()
Hello Private world! # can also be accessed internally through the public interface provided by the class
In [136]: My_instance._my_class__private_variable
OUT[136]: 1
17, exception handling plus else
Copy Code code as follows:
In [i]: try:
...: print (' third element: ', a_list[2])
...: except Indexerror:
...: Print (' Raised indexerror ')
.....: Else:
...: Print (' no error in Try-block ') # The expression in else is executed only when there is no exception in the try
.....:
Raised Indexerror # threw an anomaly, not completely finished.
In [153]: i = 0
In [154]: While I < 2:
.....: Print (i)
.....: i + 1
...: else:
.....: print (' in Else ')
...:
0
1
in else # while also supported Oh ~
in [?]: i = 0
In [156]: While I < 2:
.....: Print (i)
.....: i + 1
.....: break
...: else:
.....: print (' Completed While-loop ')
...:
0 # was break not executed completely without execution else inside of the
In [158]: For I in range (2):
.....: Print (i)
...: Else:
.....: print (' Completed For-loop ')
...:
0
1
completed For-loop
In [159]: For I in range (2):
...: print (i)
...: Break
.....: Else:
...: Print (' Completed For-loop ')
.....:
0 # Because of the break.