파이썬(python) 변수 값 복사하기(오해)
이전 게시글에서 파이썬에서 변수란 값이 저장되어 있는 메모리의 주소를 가리킨다고 했다. 따라서 아래 코드와 같이 a라는 변수에 저장된 값을 b에 복사하기 위해 b = a라고 하면 나중에 값을 변경할 때 문제가 생긴다. 왜 그럴까? 아래 실행 결과인 그림을 보면 알 수 있다.
a = [1, 2, 3]
b = a
위 그림을 보면 변수 a와 b 모두 같은 리스트 자료형 값을 가리키고 있는 것을 볼 수가 있다. 두 변수가 같은 객체를 가리키고 있는 것이다. 이것은 a와 b 두 변수가 완전히 동일하다는 것을 의미한다. 이렇게 된 이유는 b = a라고 함으로써 b도 a가 가지고 있는 [1, 2, 3]을 참조하라고 명령을 내렸기 때문이다. 좀 더 자세한 사항을 알기 위해 아래와 같은 코드를 실행해 보자.
a = [1, 2, 3]
b = a
print(id(a))
print(id(b))
여기서 id() 함수는 ( )안에 들어간 변수가 가리키고 있는 객체의 주소 값을 돌려주는 역할을 하는 파이썬 내장 함수이다. 실행 결과는 아래와 같다.
두 변수 a, b가 참조하는 주소 값이 완전히 동일한 것을 볼 수가 있다. 이로부터 a와 b는 변수 이름만 다를뿐 가리키는 주소 값은 같다는 것을 알 수가 있다. 즉, 두 변수 a, b에 저장된 값은 같다. 이는 두 변수 각각을 독립적으로 다른 값을 저장하려고 할 때 문제가 생길 수 있다. 어떤 문제가 생기는지 아래 코드를 보자.
a = [1, 2, 3]
b = a
a[1] = 4
print(a)
print(b)
a[1] = 4로 하여 a의 2번째 요소를 4로 바꿔 a=[1, 4, 3]으로 만들어 줬다. 그러고 나서 a와 b 변수가 가지고 있는 값을 따로 출력을 했다. 그랬더니 아래와 같은 결과가 나왔다.
a와 b 값 모두 [1, 4, 3]으로 똑같이 출력된 것을 볼 수가 있다. 이는 아까도 말했듯이 a와 b가 같은 객체를 가리키고 있기 때문이다. 따라서 a에 저장된 값을 바꾸면 b도 같은 값을 가리키므로 두 변수 a, b는 항상 같은 값을 가진다.
코드 실행 결과를 시각적으로 보여준 위 그림을 보면 쉽게 이해할 수 있을 것이다. Frames에 있는 두 변수 a, b의 화살표가 동일한 list를 가리키고 있는 것이 보이는가? 이는 두 변수 a, b가 이름만 다를뿐 같은 값을 참조한다는 것을 뜻한다.
파이썬(python) 변수 값 복사 방법
파이썬의 어떤 변수의 값만 복사하려면 2가지 방법을 쓸 수 있다. 바로 (1) [:]와 (2) copy 모듈을 사용하는 방법이다. 이 방법들은 변수의 값만 가져오고 다른 주소만 참조하게 하여 원래 변수가 변하더라도 영향을 받지 않는다. 그럼 바로 그 방법들을 알아보자.
(1) [:]를 이용한 복사
a = [1, 2, 3]
b = a[:]
a[1] = 4
print(a)
print(b)
[:]는 리스트의 모든 값을 슬라이싱(slicing)하는, 즉 모든 값을 가져오는 방법이다. a[:]는 a 리스트 변수의 모든 요소를 다 복사하여 가져오므로 b = a{:]을 하게 되면 b에 순수하게 a의 값들만 복사된다. 이때 변수 b는 a와 값만 같은 객체를 가리키게 되므로 아래 그림과 같이 변수 a, b는 서로 다른 주소를 가리키게 된다. 따라서 a[1] = 4을 하여 a의 값을 바꾸더라도 b 값은 영향을 받지 않고 [1, 2, 3] 값을 그대로 갖고 있게 된다.
실행 결과를 보면 서로 다른 주소 값을 가리키므로 a와 b의 값이 서로 다르게 출력된 것을 볼 수가 있다.
(2) copy 모듈을 사용한 복사
from copy import copy
a = [1, 2, 3]
b = copy(a)
print(a)
print(b)
print(a is b)
copy 모듈을 사용하면 해당 변수 값을 그대로 복사하기만 할 수 있다. 위 코드에서 from copy import copy라는 구문이 맨 첫 줄에 오는데, 이것은 'copy 모듈로부터(from) copy 함수를 가져오겠다(import)'는 것을 의미힌다. 따라서 첫 줄을 지나면 copy() 함수를 쓸 수 있게 된다. copy() 함수는 ( )에 들어있는 변수의 값을 복사하여 반환한다. 즉, copy(a)는 a[:]와 동일하다. 그러므로 위 코드에서 b = copy(a)는 b = a[:]와 동일한 결과를 보여준다.
위 코드를 실행하면 아래와 같은 결과를 보여준다.
변수 a와 b가 서로 다른 주소를 가리키는 볼 수가 있다. 따라서 a에 저장된 값을 바꿔도 b 값은 변하지 않고, 그 반대로 마찬가지다. 실행 결과는 아래와 같다.
실행 결과 마지막 줄에 False라고 나와있는데, 이것은 위 코드에서 print(a is b) 구문 때문에 나온 것이다. a is b는 a와 b가 동일한 객체를 가리키고 있으면 True(참)를, 아니라면 False(거짓)를 반환한다. 다시 말해서, a is b는 id(a)와 id(b) 값이 같은지 아닌지를 판별하여 준다. 따라서 a is b의 실행 결과가 False인 것은 변수 a와 b가 가리키는 메모리 주소가 서로 다르기 때문임을 알 수 있다.
'프로그래밍 > 파이썬' 카테고리의 다른 글
파이썬(python) 리스트 내포(List comprehension) (0) | 2022.04.02 |
---|---|
파이썬(python) 시각화 사이트 (0) | 2022.04.02 |
파이썬(python)의 변수란? (0) | 2022.04.02 |
cmd에서 python 파일명.py 입력 후 python이라고 뜨는 문제 (2) | 2022.03.26 |
파이썬(Python) "PRN 장치를 초기화할 수 없습니다." 해결 방법 (0) | 2022.03.25 |
댓글