IT

파이썬 2차원 배열 선언 이해하기 (깊은 복사 얕은 복사)

happy_life 2022. 4. 27. 18:18
array = [[0] * 3 for _ in range(3)]
array = [[0] * 3] * 3

위의 코드를 출력해보면 겉으로 보기엔 똑같습니다.

 

하지만 array[0][1] = 1을 넣고 출력해보면 결과가 다릅니다.

 

왜 이런 결과가 나오는지는 immutable 객체와  mutable 객체로 설명할 수 있는데,

mutable - 변경 가능 객체

immutable - 변경 불가능 객체

mutable 객체에는 list,set,dictionary 정도가 있고

immutable 객체에는 int, float, tuple, str, bool 등이 있습니다.

 

immutable 객체는 깊은 복사를 하고

mutable 객체는 얕은 복사를 합니다.

 


array = [[0] * 3] * 3

array = [[0] * 3] * 3

여기서 [0] * 3 을 하는 것은 [0,0,0]을 만든다. 여기서 0 은 int형으로 immutable하고 따라서 이는 깊은 복사되고

[0,0,0] * 3은 mutable 해 얕은 복사가 됩니다.

따라서 각각의 [0,0,0] 은 복사가 되었지만, 실제로는 같은 곳을 참조하고 있는 것입니다. 따라서 array[0][1] = 1로 값을 추가해준 경우 각각의 [0,0,0]에 영향을 주어 위와 같은 결과가 도출된 것입니다.


array = [[0] * 3 for _ in range(3)]

array = [[0] * 3 for _ in range(3)]

이 것도 겉보기엔 비슷하게 동작하는 것같은데 왜 다른 결과가 나올까요? 위의 코드는 사실아래와 같게 동작하는 것입니다.  기존의 것을 복사하는 것이 아니라, 새롭게 할당해주는 것이기 때문에 영향을 받지 않습니다. 새로운 배열이 return 될 때는 oper에 들어가는 메모리 주소가 아예 다릅니다. 복사되는 것이 아니라 새롭게 할당되는 것입니다. 


a = [0,0,0]
b = [a for _ in range(3)]

print(hex(id(b[0])))
print(hex(id(b[1])))
print(hex(id(b[2])))

그렇다면 이건 어떨까요?? 

왜 이런 결과가 나올까요? 

이미 할당된 것을 넣어주는 것이기 때문입니다.

쉽게 말해 같은 철수를 3번 넣어준 것입니다. 메모리주소가 같습니다. 메모리 주소가 같으니 같은 값이 나옵니다.