본문 바로가기

Python/Python 기초

리스트 레퍼런스 (List References)

출처: http://inventwithpython.com/chapter10.html



파이썬에서 리스트와 딕셔너리는 특별해서 이를 함수에 파라미터로 넘겨줘서 값을 바꿔도

함수 바깥에서도 값이 없어지지 않는다.

리스트(혹은 딕셔너리)에 대한 레퍼런스를 넘기지, 리스트 자체를 넘겨주는 것은 아니다.

이제 리스트와 리스트 레퍼런스의 차이를 알아보자.


다음 코드를 셸에 입력해 보자.


1
2
3
4
5
6
7
>>> spam = 42
>>> cheese = spam
>>> spam = 100
>>> spam
100
>>> cheese
42


지금까지 알고 있는 바로는 위의 결과는 당연하다.

spam에 42를 대입한 다음 이 값을 cheese 변수에 대입했다. 그러고 나서

spam의 값을 100으로 바꾸면 이것은 cheese 변수에는 영향을 주지 않는다.

spam과 cheese는 서로 다른 값을 저장하는 변수이기 때문이다.


하지만 리스트에서는 이렇게 작동하지 않는다.

리스트를 다른 변수에 = 으로 활당하면 사실은 리스트 레퍼런스를 대입한 것이 된다.

레퍼런스는 데이터의 부분을 가리키는 값이며 리스트 레퍼런스는 리스트를 가리키는 값이다.,


이해하기 쉽게 다음을 셸에 입력해 보자.


1
2
3
4
5
6
7
>>> spam = [0, 1, 2, 3, 4, 5]
>>> cheese = spam
>>> cheese[1] = 'Hello!'
>>> spam
[0, 'Hello!', 2, 3, 4, 5]
>>> cheese
[0, 'Hello!', 2, 3, 4, 5]


이상해 보이지 않나? 코드에서는 cheese 리스트만 바꿨는데 cheese와 spam 리스트가 모두 바뀌었다.

cheese = spam은 spam의 리스트 레퍼런스를 cheese에 복사한다. 리스트 자체를 복사하지 않는다.

원래 spam 변수의 값 또한 리스트 레퍼런스이지, 리스트 자체가 아니다.

따라서 spam과 cheese는 동일한 리스트를 가리키는 값을 가진다.

리스트는 복사한 적이 없으므로 단 하나밖에 없고 리스트에 대한 레퍼런스만 복사했다.

따라서 cheese[1] = 'Hello!'처럼 cheese를 바꾸면 spam이 가리키는 리스트를 바꾸게 된다.

따라서 spam과 cheese가 똑같은 리스트 값을 보여준다.


변수란 값을 저장하는 상자와 같다. 리스트 변수는 사실 리스트 자체를 포함하지 않고,

리스트에 대한 레퍼런스만을 포함한다. 아래 그림은 여러분이 코드를 입력했을 때 어떤 일이 벌어지는지 보여주고 있다.



변수는 리스트를 저장하지 않고, 리스트에 대한 레퍼런스를 저장한다.

리스트 자체는 어떤 변수에도 저장되지 않는다. 다만 리스트를 가리키는 레퍼런스만을 저장한다.




두 변수는 각각 레퍼런스를 저장하는데 동일한 리스트를 가리킨다.

spam에 들어있는 레퍼런스를 cheese에 할당하면 cheese 변수는 spam에 들어 있는 레퍼런스 값을 복사해서

가지게 된다. 이제 cheese와 spam은 동일한 리스트를 가리킨다.



리스트를 바꾸면 리스트를 가리키는 모든 레퍼런스 변수를 바꾸게 된다.

cheese가 가리키는 리스트를 수정하면 spam이 가리키는 리스트도 바뀐다.

두 변수가 동일한 리스트를 가리키기 때문이다.

spam과 cheese가 서로 다른 리스트를 저장하려고 하면, 레퍼런스를 복사하지 말고


1
2
>>> spam = [0, 1, 2, 3, 4, 5]
>>> cheese = [0, 1, 2, 3, 4, 5]

위 코드처럼  처음부터 다른 리스트를 만들어야 한다.


위의 예에서는 spam과 cheese가 서로 다른 리스트를 저장한다 (물론 내용은 같다). 이제 이 리스트 중 하나를 고쳐도

다른 리스트에는 영향을 주지 않는다. spam과 cheese는 서로 다른 리스트에 대한 레퍼런스를 저장하기 때문이다.


1
2
3
4
5
6
7
>>> spam = [0, 1, 2, 3, 4, 5]
>>> cheese = [0, 1, 2, 3, 4, 5]
>>> cheese[1] = 'Hello!'
>>> spam
[0, 1, 2, 3, 4, 5]
>>> cheese
[0, 'Hello!', 2, 3, 4, 5]



두 변수는 각각 서로 다른 리스트에 대한 레퍼런스를 저장한다.



참고로 딕셔너리도 똑같이 동작한다.

딕셔너리도 값을 저장하지 않고, 값에 대한 레퍼런스만을 저장한다.

이것을 딕셔너리 레퍼런스(dictionary reference)라고 하는데 딕셔너리 레퍼런스든,

리스트 레퍼런스든 간에 그냥 둘다 레퍼런스라고 부른다.





'Python > Python 기초' 카테고리의 다른 글

파이썬의 문자열  (0) 2014.10.24
None 값 (The None Value)  (0) 2014.09.26
다중 대입 (Multiple assignment)  (0) 2014.09.24
딕셔너리 (dictionart), 맵(map)  (0) 2014.09.24
리스트 (list) 와 문자열의 메서드  (0) 2014.09.18