brunch

You can make anything
by writing

C.S.Lewis

by 이권수 Mar 12. 2024

[Python] 파이썬 변수의 실제 역할

파이썬 변수의 숨겨진 실제 역할은?


파이썬은 변수를 정의할 때 별도로 타입을 지정하지 않는다. 언뜻 보면 파이썬이 값을 보고 변수에게 타입을 알려주는 것처럼 보일 수 있다. 하지만 실제로 파이썬 변수는 그렇게 동작하지 않는다.


파이썬에서 변수는 단순히 기호(Symbol, 심볼)에 불과하다. 심볼은 특정 메모리 공간을 가리키기 위한 일종의 기호일 뿐이다. 다시 말해 변수는 메모리를 가리키는 변수에 불과하다. 실제 값은 메모리에 저장되어 있고, 해당 메모리 공간을 알파벳으로 구성된 심볼을 통해서 가리키고 있는 것이다. 따라서 실제로 변수가 담고 있는 값은 메모리 공간의 주소이다.


예컨대, a = 10으로 변수를 정의하면 실제로는 아래와 같은 그림이 구성된다. 먼저 파이썬은 10이라는 값을 담고 있는 객체를 생성한다. 객체의 타입은 int이다. 해당 객체가 저장된 메모리 주소를 a라는 심볼이 가리키도록 설정한다. 이때 다른 변수들도 같은 객체를 가리키도록 정의할 수도 있다.

파이썬의 변수는 실제로 메모리를 가리킬 뿐이다.


코드에서도 이를 확인할 수 있다. 먼저 a, b, c 모두 10이라는 값을 할당한다. 이때 a, b, c의 실제 주소값을 찾아보면 4330629728로 모두 같은 것을 확인할 수 있다. 이후에 a의 값을 20으로 변경하면, a가 가리키는 주소만 달라진다.



이 구조를 이해하면 파이썬이 어떻게 동적 타입 할당을 지원하는지 알 수 있다. 앞서 설명한 것처럼 파이썬은 변수를 할당할 때, 실제 값을 객체에 담아서 메모리에 저장한다. 각 객체는 타입이 존재하는데, 이건 값이 따라서 파이썬이 알아서 정해준다. 변수 자체는 객체의 타입과 따로 연결되지 않는다. 그래서 중간에 같은 변수에 다른 타입의 값을 넣어도 상관이 없다. 실제로는 가리키는 메모리 공간이 달라졌을 뿐이지, a 변수에 들어있는 값 자체가 달라진 것은 아니기 때문이다. 


아래는 중간에 변수에 다른 타입을 지정하면 어떤 과정을 거치는지에 대한 예시이다.

파이썬 변수는 실제로 객체의 메모리를 저장할 뿐이다!



이 원리를 머릿속에 각인시키면 변수를 유연하게 다룰 수 있다. 예컨대, 함수를 다룰 때 기존에 제공하던 함수가 아니라 내가 원하는 함수로 바꿔치기를 할 수 있다. 


print라는 함수를 예로 들어보자. print는 stdout으로 값을 쓰는 함수이다. 보통은 콘솔에서 결과를 확인할 때 많이 사용한다. print는 내장함수로, 별도의 패키지를 설치하지 않아도 사용할 수 있다. print 자체를 출력해 보면 function 타입임을 알 수 있다. 그리고 isinstance함수를 통해서 print로 object 임을 알 수 있다. id를 출력해 보면 실제 메모리 주소가 나온다.


그런데, 중간에 print라는 변수에 다른 함수를 할당한다고 가정해 보자. 아래는 두 수를 더하는 lambda함수를 만들고, 해당 객체를 print라는 변수가 가리키도록 변경한 예시이다. 그 후에 print 함수에 두 정수를 넘기면, 덧셈 결과를 출력해 준다. 마치 add, sum과 같은 함수 역할을 하는 것이다.


참고로, 전역 변수를 모두 확인하고 싶다면 globals()라는 내장함수를 사용할 수 있다. globals()는 어떤 변수가 어떤 객체를 가리키고 있는지를 알려준다. 여기서 'print'를 키워드로 찾아보면, 다음과 같이 lambda 함수를 가리키고 있음을 알 수 있다.




요컨대, 파이썬 변수는 실제로 메모리 영역을 가리키는 심볼에 불과하다. 실제 값은 객체형태로 메모리에 저장된다. 이러한 내부 구조 덕분에 파이썬은 동적 타입 할당을 지원할 수 있는 것이다.


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari