This is the first article in the series " Brush Questions and Avoid Pitfalls ". This series helps you avoid common pitfalls in brushing questions/codes.
strange things
In Python, the ways to define a one-dimensional list (that is, an array ) whose 3
length is , and whose values are all are :0
a = [0, 0, 0]
a = [0 for _ in range(3)]
a = [0] * 3
When brushing algorithm questions, we often encounter a scenario where we need to define a one-dimensional list with the same length as the input. Therefore, I basically use the third method mentioned above.
like:
a = [0] * len(nums)
Assuming that nums
the length of is 5, then after running the above code, a
the value of is [0, 0, 0, 0, 0]
.
Let's modify a
the list:
In [1]: a[0] = 666
In [2]: a
Out[2]: [666, 0, 0, 0, 0]
As you can see, modifying the th element a
of the list does not affect elements in other positions.0
This is a matter of course.
However, when the array becomes two-dimensional, strange things happen .
According to the idea of defining a one-dimensional array above, define a two-dimensional array of 3
rows and 2
columns b
:
In [1]: b = [[0] * 2] * 3
In [2]: b
Out[2]: [[0, 0], [0, 0], [0, 0]]
It seems b
to meet the requirements, no problem.
However, when we modify b
the elements in the :
In [1]: b[0][0] = 2333
In [2]: b
Out[2]: [[2333, 0], [2333, 0], [2333, 0]]
see it? We only modified it b[0][0]
, but all the elements b
in the column of the list have been modified! 0
!
Isn't it weird? ?
analyze
When encountering such a strange problem, you can use the [code execution visualization tool] that I shared before for analysis.
The address of this tool is:https://pythontutor.com/
Let's first look at the visual operation of Python one-dimensional list in memory.
As can be seen from the animation above, modifying an element in a one-dimensional array does not affect other elements.
Look at the operation of the Python two-dimensional list defined in the previous way in memory.
We thought the correct two-dimensional list should be as follows . That is, the array has 3
rows, and each row is an independent list of length 2
.
But actually?
When we define b = [[0] * 2] * 3
, although it looks like the result is a 3 x 2
two-dimensional list of , in memory, each row in the array points to the same 2
list of length .
Therefore, when we modify b[0][0]
, although only one element in the memory is modified, since 3
the row points to the same address, it seems that 3
all the elements in the row are modified.
This is why weird things happen.
Let's look at the memory address of the line in the Python terminal b
( 3
you can use id()
the function to get the memory address) for verification.
In [1]: b = [[0] * 2] * 3
In [2]: for i in range(3):
...: print(id(b[i]))
...:
140178338622720
140178338622720
140178338622720
It can be seen that the row memory addresses b
of the list 3
are indeed the same, which is consistent with our visualization results above.
correct spelling
The above are common pitfalls in Python. Negative Xue was also pitted when he was brushing the questions. .
We can understand it like this:
[0] * 2
What is returned is an address in memory.- When it is defined
[[0] * 2] * 3
,[0] * 2
it only runs once and returns an addressx
; two-dimensional lists are stored ,3
ie .x
[x, x, x]
What is the correct way to write a two-dimensional array in Python?
In the first way of writing , you can explicitly write out all the elements, which will definitely be fine:
a = [[0, 0], [0, 0], [0, 0]]
In the second way of writing , we use for
to define the second dimension. is the recommended way of writing.
In [1]: a = [[0] * 2 for _ in range(3)]
In [2]: a
Out[2]: [[0, 0], [0, 0], [0, 0]]
In [3]: a[0][0] = 666
In [4]: a
Out[4]: [[666, 0], [0, 0], [0, 0]]
Why for
is it okay to use the wording?
Because [0] * 2
it is run 3
once in this case, 3
a x,y,z
. The storage in the two-dimensional list is [x, y, z]
.
The visualization results are as follows:
You can see that 3
the lines point to different addresses, so the result is as expected.
Summarize
Today I shared a common pitfall in Python brushing questions: the definition of a two-dimensional list .
We ran the visualizer through the code and analyzed why defining *
a two-dimensional array with was a problem.
Finally, the correct way of using to define a two-dimensional list is also given for
.
Knowledge of memory is very useful in programming.
It is recommended that novices use visual tools to troubleshoot when encountering such problems, which is very helpful for understanding.
The above is the first article in the series of " Brushing Questions and Hiding Pitfalls "!
Welcome to follow my public account " Negative Snow Bright Candle ". On the way of programming learning, we will step on and hide from pits together.