파이썬에는 built in 함수로 id가 있습니다. 문서에 따르면, 이것은 객체의 고유값을 리턴하는 메서드입니다. cpython은 주솟값을 돌려준다고 문서에 언급이 되어 있습니다. 저는 이 메서드를 어떤 객체를 가리키는지 보기 위해서 쓰곤 합니다. 몇 개의 예를 보고, 톡방에 질문 들어왔던 내용도 보도록 하겠습니다.

 


 예제 1입니다. 그리 어려울 것은 없습니다. a는 배열 [5]를 가리키고, b는 [10]을 가리킵니다. 이 상태에서 id(a)와 id(b)를 출력합니다. 다음에, b에 a를 대입합니다. 다음에, id(b)를 출력합니다.

 

 

 id 값을 찍어보니 위와 같이 나왔습니다. 이것을 trace 해 보도록 하겠습니다. 먼저 4번째 줄 상황을 보겠습니다.

 

 id(a)와 id(b)가 달랐습니다. a와 b가 다른 객체를 가리켰다는 의미입니다. 그런데, 5번째 줄 b = a를 수행한 후에 6번째 줄에서 b의 고유값을 출력해 보았더니, 1410006965312였습니다. 이는 id(a)와 같습니다.

 

 

 6번째 줄에서 print 된 결과를 가지고, b = a를 하면, a와 b가 가리키는 객체가 같다는 것을 파악할 수 있습니다. 문서에 따르면, life time이 겹치지 않는다면, 다른 객체라도 same id 값을 가질 수 있다고 나와 있습니다. 그러한 예제 중 하나는 어렵지 않게 코딩하실 수 있으니, gc를 할 때 다시 언급해 드리도록 하겠습니다.

 


 톡방에 들어온 질문입니다.

 

 

 위 프로그램을 보세요. 실행 결과입니다.

 

 

왜 arr이 [[20], [20], [20], [20], [20]] 으로 바뀌지 않았을까요? id 값을 보면서 trace 해 보겠습니다.

 

 

 id(i)값과 id(arr[pos]), 그리고 i = [20]이 대입된 후에 id(i)값을 print 해 보면서 trace 해 봅시다.

 

 

 36, 36, 72. 그리고 04, 04, 72. 공통점이 보이시나요? 하나 하나 보도록 하겠습니다. 먼저 iterable 한 객체의 경우 3번째 줄처럼 쓸 수 있습니다. arr은 list이니, iterable 합니다. 그러니, 저리 쓸 만 합니다. 4번째 줄과 5번째 줄에서 i와 arr[pos]가 가리키는 객체의 고유값을 출력하였습니다.

 

 

 2개의 출력값을 토대로 상황을 그려보면 위와 같음을 알 수 있습니다. 여기서, i = [20]이 들어왔는데요. 이 순간에 i가 가리키는 객체의 값이 달라졌음을 알 수 있습니다.

 

 

 이 때, i와 arr[0]은 별개의 무언가를 가리키고 있습니다. 여기까지 보았을 때, arr[0]에 뭔가 대입해라, 삭제해라. insert 하라는 코드가 없었습니다. 그러니, list의 내용은 멀쩡하게도 잘 유지가 됩니다.

 


 

 그러면 이 프로그램은 실행 결과가 어떻게 나올까요? 결과가 예상이 되지만, 객체 값을 추적하면서 보도록 하겠습니다.

 

 

 i하고 arr[pos]가 같은 객체를 가리키고 있음을 볼 수 있습니다. 그리고 list는 불변 객체가 아닙니다. 즉 append 메서드를 수행했을 때, 원본 객체를 그대로 두고 상태값을 반영한 새로운 객체를 리턴하는 게 아니라, 원본 객체에 상태 값을 반영시켜버립니다.

 

 

 그렇기 때문에, 프로그램을 수행하면, 배열들의 끝에 5가 추가되어 버립니다. 이 글에서는 id 메서드가 무엇을 하는지, 어떻게 쓰는지, 그리고 어떤 객체를 가리키는지 간단하게 디버깅 하는 방법을 알아보았습니다.