Python 2D array trap [Copy array]

It's a basic thing, but I'm stuck because I don't understand it, so make a note.

Preface

Creating an array in python is easy and nice.

a = [0] * 2
print(a) # [0, 0]

Let's also make a two-dimensional array.

b = [[0] * 2] * 2
print(b) # [[0, 0], [0, 0]]

Oh convenient. Let's operate it.

b[0][1] = 1

Let's print it.

print(b) #[[0, 1], [0, 1]]

Hmm? ?? ?? ?? ?? ??

Conclusion

Let's write this.

c = [[0] * 2 for i in range(2)]
print(c) # [[0, 0], [0, 0]]
c[0][1] = 1
print(c) # [[0, 1], [0, 0]]

Why not?

Let's use the id () function.

b = [[0] * 2] * 2
print(id(b[0])) # 1835216839944
print(id(b[1])) #1835216839944 Same address
c = [[0] * 2 for i in range(2)]
print(id(c[0])) # 1835216058120
print(id(c[1])) #1835216840392 Different address

If you copy with * 2, you will refer to the same address.

If you change the "contents" that the address refers to in the form of b [0] [1] = 1, it will be reflected in all arrays that share the address.

Why doesn't this happen with a one-dimensional array?

This phenomenon does not occur with a one-dimensional array, right?

a = [0] * 2
a[0] = 1
print(a) # [1, 0]

Let's look at the address.

a = [0] * 2
print(a[0] == a[1]) # True
a[0] = 1
print(a[0] == a[1]) # False
print(a) # [1, 0]

It had the same address when it was first copied, but when a [0] = 1 was substituted, the address changed.

This is the difference between immutable (immutable) and mutable (modifiable) references.

When manipulating a one-dimensional array, "the contents of the reference destination with an integer cannot be changed" (immutable), so by giving a different address, the value is practically changed.

When manipulating a two-dimensional array, you can change the value while keeping the address fixed because "the contents of the reference destination that has the array can be changed".

By the way

What about this kind of substitution?

#The pattern up to now
b = [[0] * 2] * 2
b[0][1] = 1
print(b) # [[0, 1], [0, 1]]
print(id(b[0]) == id(b[1])) #True

#Changed version
b = [[0] * 2] * 2
b[0] = [0, 1]
print(b) # [[0, 1], [0, 0]]
print(id(b[0]) == id(b[1])) #False

A new address will be generated. In this case, it will be treated as "redefinition" instead of "content operation", and the reference destination will be changed.

b = [[0] * 2] * 2
b[0] = [0, 0]
print(b) # [[0, 0], [0, 0]]
print(id(b[0]) == id(b[1])) #False

Reference etc.

Reference: http://delta114514.hatenablog.jp/entry/2018/01/02/233002

Postscript: The content has been revised based on the comments pointed out. I didn't understand the concept of "Python is all passed by reference" and "immutable (immutable) and mutable (modifiable)". Reference: https://snowtree-injune.com/2019/09/16/shallow-copy/

Recommended Posts

Python 2D array trap [Copy array]
Python: 3D array image (numpy.array)
Python multidimensional array
Python> link> 2D array initialization and assignment
[Beginner] Python array
Python array basics
Calculate 2D IDCT ~ Python
Copy of python preferences
[Python] Binary Acing 2020D
[python] Array slice operation
Python memo (for myself): Array
Quicksort an array in Python 3
Empty multidimensional array in python
[Python] Dynamic programming TDPC D
How to transpose a 2D array using only python [Note]
Python shallow and deep copy
python> Handling of 2D arrays
Stumble story with Python array
Solve ABC175 D in Python
Create a python numpy array
[Python] Copy of multidimensional list
AtCoder ABC 182 Python (A ~ D)
Python or and and operator trap
Python # About reference and copy
Subscript access to python numpy array
3D skeleton structure analysis with Python
Solve ABC166 A ~ D with Python
[python] Copy script to generate copy log
Python application: Numpy Part 3: Double array
[Python] How to swap array values
Compare Python and JavaScript array loops
I'm addicted to Python 2D lists
[Python scipy] Upscale / downscale 2D data
Solving with Ruby, Perl, Java and Python AtCoder ABC 131 D Array Sorting