17 Questions that Python programmers are little known about but you should know

Source: Internet
Author: User
Do not use a Mutable object as the default value of a function
Copy CodeThe code is 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 just wanted to build [2] but we 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 show? Objects such as dictionaries, collections, lists, and so on, are not suitable as default values for functions. Because this default value is generated when the function is established, each invocation uses the object's "cache". I've been sharing Python's high-level programming for a while, and that's the problem with real-world development, checking the code you've learned, and maybe it's just not revealing.

This can be changed:
Copy the 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 retain the results after the iteration
Copy the Code code as follows:

In [a]: 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 [+]: 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 [All]: 3 in A_list
OUT[23]: True

in [+]: 1 in A_list # even if the loop is over, the value is still
OUT[24]: True

Third, the lambda in the closure will save local variables
Copy the Code code as follows:


in [+]: 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 Python advanced programming for specific reasons. In fact, when I assign a value to my_list, the lambda expression executes the I loop, until I =4,i will keep

But you can use the generator
Copy the 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 CodeThe code is as follows:


In [max]: my_list = [Lambda x=i:x for I in range (5)] # Look, I've assigned a default value to each lambda expression

In [Li]: for L in My_list:
....: Print (L ())
....:
0
1
2
3
4


It's a little hard to understand. Look at another Python magic:
Copy CodeThe code is as follows:


in [+]: def groupby (items, size):
....: Return Zip (*[iter (items)]*size)
....:

In [approx]: GroupBy (Range (9), 3)
OUT[36]: [(0, 1, 2), (3, 4, 5), (6, 7, 8)]


A grouping of functions that look very difficult to understand, right? Let's get down here.
Copy CodeThe code is as follows:


In [all]: [ITER (items)]*3
OUT[39]:
[ ,
,
] # See, in fact, the items into an iterative, repeat three times (the same object OH), but do not forget, every time. Next (), so played the role of grouping
in [+]: [Lambda x=i:x for I in range (5)]
OUT[40]:
[ ,
,
,
,
Do you understand?


Iv. modifying list items in a loop
Copy the Code code as follows:

In []: a = [1, 2, 3, 4, 5]

In [the]: 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] # That's what I wanted. The result should be to remove even-numbered lists


Think about why – because you have a remove to the list that affects its index
Copy CodeThe code is as follows:


in [+]: b = [2, 4, 5, 6]

In [SI]: For index, item in enumerate (b):
....: Print (index, item)
....: If not item% 2:
....: B.remove (item)
....:
(0, 2) # There's no problem. 2 was removed
(1, 5) # because 2 is deleted the current list is [4, 5, 6], so index list[1] go straight to 5, ignoring 4
(2, 6)

V. Indexerror-the list value exceeds his index number
Copy the Code code as follows:


in [+]: my_list = [1, 2, 3, 4, 5]

in [+]: my_list[5] # There's no such element at all
---------------------------------------------------------------------------
Indexerror Traceback (most recent)
In ()
----> 1 my_list[5]

Indexerror:list index out of range # throws an exception

In [the]: my_list[5:] # But it can be, it must be noted that the use of good is trick, the wrong is the pit AH
OUT[57]: []

Vi. Reusing global variables
Copy the Code code as follows:


in [+]: def my_func ():
....: Print (VAR) # I can call an undefined variable first
....:

in [+]: var = ' Global ' # after assignment

In [MAX]: My_func () # Anyway, whenever the function is called, the variable is defined.
Global

In [i]: def my_func ():
....: var = ' locally changed '
....:

in [+]: var = ' global '

in [+]: My_func ()

in [+]: print (VAR)

Global # Local variables have no effect on globals

in [+]: def my_func ():
....: Print (VAR) # Although you set this variable globally, but the local variable has the same name, Python thinks you forgot to define the local variable.
....: var = ' locally changed '
....:

In [all]: var = ' global '

In []: My_func ()
---------------------------------------------------------------------------
Unboundlocalerror Traceback (most recent)
In ()
----> 1 My_func ()

In My_func ()
1 def my_func ():
----> 2 print (VAR)
3 var = ' locally changed '
4

Unboundlocalerror:local variable ' var ' referenced before assignment

In [the]: Def my_func ():
....: Global Var # this time it's going to add up.
....: Print (VAR) # So you can use it normally
....: var = ' locally changed '
....:

in [+]: var = ' global '

In [70]:

In []: My_func ()
Global

in [+]: print (VAR)
Locally changed # but using global has changed the world variable

Vii. Copying mutable objects
Copy the Code code as follows:

In [the]: 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 item in the sub-list

In []: My_list1
OUT[75]: [[' A ', 2, 3], [' A ', 2, 3]] # but it all affects

In [the]: My_list2 = [[1, 2, 3] for I in range (2)] # The method of generating different objects with this cycle does not affect

In [all]: my_list2[1][0] = ' a '

In [My_list2]:
OUT[78]: [[1, 2, 3], [' A ', 2, 3]]


Viii. python multiple Inheritance (C3)
Copy the 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 inherits A and B, from left to right, found a has Foo method, returned

It all looks simple, in order, from the bottom up, back to the front, to find it. Look again at the example:
Copy the 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 the C?


This also involves the MRO (Method Resolution Order):
Copy CodeThe code is as follows:


In [ten]: d.__mro__
OUT[10]: (__main__. D, __main__. B, __main__. C, __main__. A, Object)


Simple understanding is actually the new type is the breadth first, d->b, but found that C is also inherit a, first find C, and finally to find a

Ix. List of + and + =, append and Extend

Copy the Code code as follows:

in [+]: print (' ID: ', ID (a_list))
(' ID: ', 4481323592)

In []: A_list + = [1]

in [+]: print (' id (+ =): ', ID (a_list))
(' ID (+ =): ', 4481323592) # Use + = or on the original list

In []: 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 [approx]: a_list = []

In []: ID (a_list)
OUT[29]: 4481326976

in [+]: a_list.append (1)

in [+]: ID (a_list)
OUT[31]: 4481326976 # Append is added in the original list

in [+]: A_list.extend ([2])

In [ALL]: 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 the 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 [approx]: print (' "Datetime.time (1,0,0)" (1 am), bool (Datetime.time (1,0,0)))
(' "Datetime.time (1,0,0)" (1 am), True)


Xi. the difference between ' = = ' and ' is '
My understanding is ' is ' is to determine the identity of 2 objects, = = To determine the value of 2 objects
Copy the Code code as follows:


In [PNS]: a = 1

In []: b = 1

In [St]: print (' A is B ', bool (A is B))
(' A is B ', True)

in [+]: c = 999

in [+]: D = 999

In [All]: print (' C is d ', BOOL (c is D))
(' C is d ', False) # Because of Python's memory management, 5-256 of objects are cached

in [+]: print (' 257-1 ', 257-1)
(' 257-1 ', True)

in [+]: print (' 257 is 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]: a = ' Hello world! '

In []: b = ' Hello world! '

in [+]: print (' A is B, ', A is B)
(' A is B, ', False) # Obviously they're not cached, this is the object of the 2 field string

in [[]: 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 [the]: print (' A is a, ', A is a)
(' A is a, ', True)

in [+]: print (' a = = A, ', a = = a)
(' A = = A, ', False) # It's blinding my eyes ~


12, shallow copy and deep copy
We can modify the object of a list in real-world development, but we may not want to change the original list. A shallow copy copies only the parent object, and the deep copy copies the inner sub-objects of the object.
Copy the Code code as follows:


In [all]: List1 = [1, 2]

in [+]: List2 = list1 # is a reference, you operate list2, in fact, the results of List1 will change

In []: List3 = list1[:]

in [+]: Import copy

In []: List4 = Copy.copy (list1) # He's a shallow copy like List3.

In []: ID (LIST1), id (LIST2), id (LIST3), ID (LIST4)
OUT[71]: (4480620232, 4480620232, 4479667880, 4494894720)

In []: list2[0] = 3

In []: Print (' List1: ', List1)
(' List1: ', [3, 2])

In [the]: list3[0] = 4

In []: list4[1] = 4

In []: Print (' List1: ', List1)
(' List1: ', [3, 2]) # No effect on LIST3 and LIST4 operations on List1

# Look at the difference between a deep copy and a shallow copy

in [+]: From copy import copy, deepcopy

In [the]: List1 = [[1], [2]]

In [all]: List2 = Copy (list1) # or shallow copy

In [list3]: = Deepcopy (list1) # deep copy

In [ALL]: ID (LIST1), id (LIST2), ID (LIST3)
OUT[92]: (4494896592, 4495349160, 4494896088)

In [the]: list2[0][0] = 3

In [94]: Print (' List1: ', List1)
(' List1: ', [[3], [2]]) # See, if you manipulate its sub-object or the same as a reference, it affects the source

In [up]: list3[0][0] = 5

In []: Print (' List1: ', List1)
(' List1: ', [[3], [2]]) # deep copy won't affect

13, BOOL is actually a subclass of int
Copy the Code code as follows:


In [the]: Isinstance (True, int)
OUT[97]: True

In [98]: True + True
OUT[98]: 2

In [©]: 3 * true + True
OUT[99]: 4

in [+]: 3 * true-false
OUT[100]: 3

In [104]: True << 10
OUT[104]: 1024

Is the Yuan group really immutable?
Copy the Code code as follows:

In [111]: Tup = ([],)

In []: tup[0] + = [1]
---------------------------------------------------------------------------
TypeError Traceback (most recent)
In ()
----> 1 tup[0] + = [1]

TypeError: ' Tuple ' object does not support item assignment

In [113]: Tup
OUT[113]: ([1],) # I am again bright blind my eyes, clearly thrown abnormal can also be modified?

In []: Tup = ([],)

In []: Tup[0].extend ([1])

In [%]: tup[0]
OUT[116]: [1] # Well, I'm a little bit clear, though I can't manipulate tuples directly, but can't prevent me from manipulating the mutable sub-objects in tuples (list)

Here's a nice explanation. Python's + = is Weird, part II:
Copy the 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 impossible 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 does not have a private method/variable? But there can be "pseudo"
Copy the 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 a double underscore
.....: Print (' Hello private world! ')
...: def call_private_method_in_class (self):
.....: Self.__private_method ()

In [my_instance]: = My_class ()

In [133]: 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 the Code code as follows:


In [Max]: try:
...: print (' third element: ', a_list[2])
.....: Except Indexerror:
....: Print (' Raised indexerror ')
....: Else:
...: Print (' no error in Try-block ') # executes an else expression only when there is no exception in the try
.....:
Raised Indexerror # Thrown out of the ordinary not completely done
In [153]: i = 0

In [154]: While I < 2:
.....: Print (i)
.....: i + = 1
....: Else:
.....: Print (' in Else ')
.....:
0
1
In the else # while also supported Oh ~
In [155]: i = 0

In [156]: While I < 2:
.....: Print (i)
.....: i + = 1
.....: Break
....: Else:
....: Print (' Completed While-loop ')
.....:
0 # has been break, not completely executed, not executed else.
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.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.