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)