Python's two-dimensional array, have you written it right?

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 3length 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 numsthe length of is 5, then after running the above code, athe value of is [0, 0, 0, 0, 0].

Let's modify athe list:

In [1]: a[0] = 666

In [2]: a
Out[2]: [666, 0, 0, 0, 0]

As you can see, modifying the th element aof 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 3rows and 2columns b:

In [1]: b = [[0] * 2] * 3

In [2]: b
Out[2]: [[0, 0], [0, 0], [0, 0]]

It seems bto meet the requirements, no problem.

However, when we modify bthe 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 bin 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 3rows, and each row is an independent list of length 2.

image-20220323090051693

But actually?

When we define b = [[0] * 2] * 3, although it looks like the result is a 3 x 2two-dimensional list of , in memory, each row in the array points to the same 2list of length .

image-20220323085618167

Therefore, when we modify b[0][0], although only one element in the memory is modified, since 3the row points to the same address, it seems that 3all the elements in the row are modified.

image-20220323090545574

This is why weird things happen.

Let's look at the memory address of the line in the Python terminal b( 3you 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 bof the list 3are 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] * 2What is returned is an address in memory.
  • When it is defined [[0] * 2] * 3, [0] * 2it only runs once and returns an address x; two-dimensional lists are stored , 3ie .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 forto 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 foris it okay to use the wording?

Because [0] * 2it is run 3once in this case, 3a x,y,z. The storage in the two-dimensional list is [x, y, z].

The visualization results are as follows:

image-20220323092713004

You can see that 3the 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.

Guess you like

Origin blog.csdn.net/fuxuemingzhu/article/details/123698243