Mutable vs Immutable
파이썬의 객체는 생성 후 값을 변경할 수 있는지 여부에 따라 mutable, immutable로 나뉜다.
객체의 값을 변경할 수 있다는 것은, 그 값이 변경돼도 같은 메모리 주소를 가진다는 것을 의미한다.
그래서 mutable 객체인 List는 값을 막 바꿔봐도 id가 변하지 않는다.
x = [1,2,3]
y = x
print(id(x))
print(id(y))
y[0] = 3
print(id(y))
print(id(x))
2062815432192
2062815432192
2062815432192
2062815432192
하지만 immutable 객체인 int의 경우 값을 바꾸면 id가 변하게 된다.
이는 값이 변경되면서, 기존과 다른 새로운 객체를 가리키기 때문이다.
x = 1
y = x
id(1)
>> 140706521527120
id(x)
>> 140706521527120
id(y)
>> 140706521527120
y += 3
id(y)
>> 140706521527216 # 값이 바뀌어 id가 변경 -> immutable
Object Interning(객체 재사용)?
값이 변경되지 않는 것이 보장된 immutable 객체라면, 미리 정의된 정보를 재사용하더라도 별 문제가 없을 것이다.
어차피 변하지 않으니까.
오히려 이 경우 Heap 영역의 메모리를 아낄 수 있다는 장점이 있다.
이처럼 immutable 객체를 재사용하여 메모리를 절약하는 방법을 Object Interning라고 한다.
Interning을 효율적으로 활용하기 위해서, CPython에선 자주 활용되는 숫자나, 문자열을 미리 저장해둔다.
따라서 Interning은 메모리 절약 기법인 동시에, 일종의 캐싱 기법이라고 할 수 있다.
- 그래서 인터프리터 버전에 따라서 다른 id 결과가 출력될 수 있다.
CPython에서 기본적으로 Interning하는 객체는 다음과 같다.
str : 20자 미만의 공백을 포함하지 않는 문자열
int : -5 부터 256 사이의 정수
Object Interning의 결과를 코드를 통해 실제로 확인해보자.
i = 10
j = 10
print(id(i), id(j), i is j) #2008444256 2008444256 True
x = 257
y = 257
print(id(x), id(y), x is y) #2611825055632 2611825055568 False
숫자 10과 달리, 숫자 257은 범위가 초과하여 Object Interning이 되지 않아 id 값이 서로 다름을 확인할 수 있다.
나는 실행 결과가 다른데?
기본적으로 Interning은 조건에 맞으면 실행되는 것이 맞다.
하지만 Interning은 최종적으로 파이썬이 유저가 입력한 코드를 바이트 코드로 변경하는 과정에서 확정된다. 따라서 컴파일러가 판단에 따라서 Interning 추가로 진행될 수도, 또 아닐 수도 있다고 한다.
참고
- Object Interning이 추가로 일어날 수 있음을 확인
- Object Interning에 대한 개념 확인