본문 바로가기
프로그래밍/파이썬

파이썬(python) 변수의 값 복사하기

by 블랜드 2022. 4. 2.
반응형

파이썬(python) 변수 값 복사하기(오해)

 

파이썬(python)의 변수란?

변수  파이썬에서 변수는 객체(Object)를 가리킨다. 여기서 객체란 메모리 상에 있는, 프로그래밍 조작의 대상이 되는 것을 말한다. 즉, 변수는 자료형(객체)이 담고 있는 메모리의 주소를 가리키

recall.tistory.com

 이전 게시글에서 파이썬에서 변수란 값이 저장되어 있는 메모리의 주소를 가리킨다고 했다. 따라서 아래 코드와 같이 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, 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는 항상 같은 값을 가진다.

동일한 객체를 참조하는 두 변수 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
실행 결과

 실행 결과를 보면 서로 다른 주소 값을 가리키므로 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가 서로 다른 주소를 가리키는 볼 수가 있다. 따라서 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가 가리키는 메모리 주소가 서로 다르기 때문임을 알 수 있다. 

반응형

댓글