Python common pit summary

Posted by Gillesie on Wed, 11 Mar 2020 13:08:44 +0100

1. List and * operation

In Python, the * operator is used in combination with list to copy elements.

Copy 5 empty lists:

In [1]: [[]] * 5
Out[1]: [[], [], [], [], []]

In [2]: a = [[]] * 5

In [3]: a
Out[3]: [[], [], [], [], []]

In [4]: 

Fill two elements:

In [4]: a[0].extend([1,2,3])

In [5]: a[1].extend([4,5,6])

Expectations should be:

[[1,3,5],[2,4,6],[],[]]

The actual situation is:

In [6]: a
Out[6]: 
[[1, 2, 3, 4, 5, 6],
 [1, 2, 3, 4, 5, 6],
 [1, 2, 3, 4, 5, 6],
 [1, 2, 3, 4, 5, 6],
 [1, 2, 3, 4, 5, 6]]

The identifiers of a[0], a[1],..., a[5] copied by the original * operation are equal in memory, and only shallow copy is implemented.

In [7]: id(a[0])
Out[7]: 1641831703560

In [8]: id(a[1])
Out[8]: 1641831703560

In [9]: id(a[2])
Out[9]: 1641831703560

In [10]: id(a[3])
Out[10]: 1641831703560

In this scenario, it is hoped that the id[0] and id[1] are not equal. Modifying a[1] will not affect a[0].
Without * and using list generation, five embedded lists with different IDs are copied, so that the assignment is not interfered with each other.

In [12]: b = [[] for _ in range(5)]

In [13]: b
Out[13]: [[], [], [], [], []]

In [14]: id(b[0])
Out[14]: 1641875609928

In [15]: id(b[1])
Out[15]: 1641875595080

In [16]: id(b[2])
Out[16]: 1641875822344

In [17]: b[0].extend([1,2,3])

In [18]: b[1].extend([4,5,6])

In [19]: b
Out[19]: [[1, 2, 3], [4, 5, 6], [], [], []]

In [20]: 

2. Delete list element

If the list has duplicate elements, to delete the specified elements in the list, see the following code:

In [20]: def del_list(a, x):
    ...:     for i in a:
    ...:         if i == x:
    ...:             a.remove(i)
    ...:     return a
    ...:     

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

In [22]: del_list(a, 2)
Out[22]: [1, 3, 4]

In [23]: del_list([1,2,3,4,3,4,3], 2)
Out[23]: [1, 3, 4, 3, 4, 3]

In [24]: del_list([1,2,3,4,3,4,3], 3)
Out[24]: [1, 2, 4, 4]

In [25]: del_list([1,3,5,3,2], 3)
Out[25]: [1, 5, 2]

You can see that the above deletions are correct, and then look at the following code

In [26]: del_list([1,3,3,3,3,5], 3)
Out[26]: [1, 3, 3, 5]

As you can see, the deletion result is still containing 3. Why?

Traverse the list a and remove once, and reduce the index of all elements after i is removed. Therefore, once the deleted element repeatedly appears in the list, one element that should be deleted will always be missed.

The correct way is to delete the deleted element after it is found, and at the same time, the next traverse index will not be increased by one; if it is not found, the traverse index will be increased by one.

Generally speaking, try to avoid deleting and updating the list in the process of list iteration.

3. The function default parameter is null

The parameters of Python functions can be set to default values. If a default parameter type is list, the default value is set to [].
There are the following functions:

In [27]: def add_list(value, volume=[]):
    ...:     if volume is None:
    ...:         volume = []
    ...:     length = len(volume)
    ...:     for i in range(length):
    ...:         volumn[i] = i + value
    ...:     return volume
    ...: 


Call the add UU list function. The val value is 10, and the volume default value. The function returns a list with an empty ret.

In [28]: ret = add_list(10)

In [29]: ret
Out[29]: []

In [30]: 

Then, we add values 1 and 2 to the empty list ret, and print ret, and the result is in line with the expectation

In [30]: ret.append(1)

In [31]: ret.append(2)

In [32]: ret
Out[32]: [1, 2]

In the same way, call the add UU list function again, and the second parameter still takes the default value. The expected return value ret is still an empty list, but the result is unexpected!

In [41]: ret = add_list(10)

In [42]: ret
Out[42]: [10, 11]

Why is the return value [10,11]? According to the results, we guess that [1,2] + 10 is not exactly [11,12].

When the original function is called add UU list, the default parameter volume is the default value, and volume is the return value of the function. Then do some operations outside the function, call again according to the default value, and return. During the whole process, the id of the default parameter volume remains unchanged.

We can see from the increase of printing that the id of the default parameter volume has never changed.

In [45]: ret = add_list(10)
volume id is 1641863237000

In [46]: ret.append(1)

In [47]: ret.append(2)

In [48]: ret 
Out[48]: [1, 2]

In [49]: ret = add_list(10)
volume id is 1641863237000

In [50]: ret
Out[50]: [10, 11]

To avoid this hidden pit, remember that the default parameter value of the function cannot be set to [], but to None. This avoids this risk even if called multiple times by default.

In [53]: def add_list(value, volume=None):
    ...:     print("volume id is {}".format(id(volume)))
    ...:     if volume is None:
    ...:         volume = []
    ...:     length = len(volume)
    ...:     for i in range(length):
    ...:        volume[i] = i + value
    ...:     return volume
    ...:     

In [58]: ret = add_list(10)
volume id is 1929553104

In [59]: ret
Out[59]: []

In [60]: ret.append(1)

In [61]: ret.append(2)

In [62]: ret
Out[62]: [1, 2]

In [63]: ret = add_list(10)
volume id is 1929553104

In [64]: ret
Out[64]: []

4. {} and ()

To be recognized as a tuple, a single element must be followed by a comma, as shown in the following code:

In [65]: a = (10)

In [66]: type(a)
Out[66]: int

In [67]: b = (10,)

In [68]: type(b)
Out[68]: tuple

Create a collection and a dictionary, both of which use a pair of {}, but return the dictionary by default instead of the collection. To create an empty set, use the built-in function set()

In [69]: d = {}

In [70]: type(d)
Out[70]: dict

In [71]: s = set()

In [72]: type(s)
Out[72]: set

5. Order of multi value assignment


Multi value assignment is to calculate all variable values on the right side of the equal sign, and then assign them to variables on the left side of the equal sign.

In [73]: a, b = 1, 2

In [74]: a, b = b+1, a+b 

In [75]: a, b
Out[75]: (3, 3)
167 original articles published, 20 praised, 50000 visited+
Private letter follow

Topics: Python