흔하게 발생하는 리스트 복사 오류에 대해 알아보고 제대로 복사하는 방법은 무엇인지 알아보자.
1. 흔하게 발생하는 리스트 복사 오류 - 초급
리스트를 = 이렇게 할당하게 되면 리스트가 복사가 되는것이 아니라 리스트가 저장된 메모리 주소가 복사가 되는것이다. 이말은 집열쇠를 복사하는 것과 똑같은데, 집열쇠를 복사한다고 해서 집이 2개가 되는게 아닌것 처럼말이다. 예시를 통해서 왜 잘 못되었는지 알아보자.
a = [1, 2, 3]
b = a
# b 에 요소를 변경해보자.
b[0] = 0
print(a, b) # [0, 2, 3], [0, 2, 3]
print(id(a), id(b)) # a.b의 메모리 주소가 동일
a와 b의 변수는 동일한 메모리주소를 가지고 있어서, b의 요소를 변경했을때 a 도 변경된 것을 확인할 수 있다.
2. 흔하게 발생하는 리스트 복사 오류 - 중급
1번의 문제를 해결하고자 흔하게 사용하는 복사 방법은 슬라이싱, copy(), list()등의 방법들을 이용한다. 상황에 따라서 맞기도 하고 틀리기도 하다. 무슨말인지 예시를 통해 알아보자.
a = [1, 2, 3]
b = a[:] # 슬라이싱을 통해 리스트 복사하는 방법
print(id(a), id(b)) # 두개의 변수 아이디 (메모리 주소) 가 다른것을 확인
b[0] = 0 # 재할당
print(a, b) # [1,2,3] , [0,2,3] a와 b가 서로 영향을 주지 않음
이 상황의 경우에는 리스트의 메모리주소가 달라서 완벽하게 복사가 된 것같다. 하지만 여기에 함정이 있다. 각 요소들의 메모리 주소를 확인해보자.
a=[1,2,3]
b=a[:]
print(id(a[0]), id(b[0])) # 각 요소의 메모리주소가 동일함
b[0] = 0
print(id(a[0]), id(b[0])) # 재할당되면서 메모리주소가 변경
a = [[1], [2], [3]]
b = a[:]
b[0].append(1) # 재할당하지 않고 list에 append할 경우
print(a, b) # [[1,1], 2, 3] , [[1,1], 2, 3] a, b가 동시에 변경됨
리스트자체의 메모리 주소는 다르지만, 리스트 안에있는 요소들의 주소는 동일하다. 그리고 재할당을 하게되면 주소가 새로 부여되면서 서로 영향을 미치지 않지만 문제는 리스트 내의 리스트와 같은 ** mutable 객체 일경우에는 문제가 발생할 수 있다. 재할당을 하지 않고 list의 append 함수를 사용할 경우에는 각 요소의 메모리 주소가 변경되지 않아 a,b 변수가 같이 변경이 되는 것을 볼 수 있다.
**mutable 객체와 immutable 객체
Mutable 객체 : list, set, dict
Immutable 객체 : bool, int, float, tuple, str, frozenset
3. 제대로 복사하는 방법 deepcopy
Deepcopy 함수를 사용하여 리스트와 리스트의 각 요소들의 메모리 주소까지 다르게 복사가 가능하다. 이렇게하면 철저히 복사하여 서로 영향을 받지 않지만 많은 메모리와 시간이 소요되는 단점이 있다. 따라서 리스트의 내에 요소들이 mutable 객체인지, immutable 객체인지 판단하여 상황에 맞게 사용하는 것이 중요하다.
import copy
a = [[1], [2], [3]]
b = copy.deepcopy(a)
print(id(a), id(b)) # 리스트의 메모리주소가 다른것을 확인
print(id(a[0]), id(b[0])) # 리스트의 각 요소의 메모리 주소가 다른것을 확인
'IT > Python' 카테고리의 다른 글
[Python] Mac 에서 아나콘다 활용방법 - 가상환경 생성, 필요한 라이브러리 설치 (0) | 2022.09.01 |
---|---|
[Python] 딕셔너리에 키 값 확인하고 자동으로 값 생성하기 (0) | 2022.08.31 |
[python] 특정 문자 위치 찾기, 특정 문자 개수 찾기 (0) | 2022.08.29 |
[Python] 파이썬 문자와 숫자 형식의 저장방식 차이 ( 문자열 인덱싱, 입력, 출력) (0) | 2022.08.11 |
[Python] Dictionary 자료형 (0) | 2022.08.08 |