파이썬의 작은 데이터 풀: 정수 및 문자열 객체 재사용 메커니즘

정수 객체의 재사용 범위

다음 코드를 예로 들어보겠습니다:

a = 5
b = 5
print(a is b)  # True

x = -7
y = -7
print(x is y)  # True

m = 300
n = 300
print(m is n)  # 대화형 모드에서는 True, 스크립트 파일에서는 일반적으로 True (최적화 적용 시)

결과는 실행 환경에 따라 다를 수 있습니다. 인터랙티브 셸(예: IDLE 또는 REPL)과 파이썬 스크립트 파일(.py) 내에서 동작이 약간 다릅니다. 하지만 CPython 구현체 기준으로 컴파일 타임 최적화가 이뤄지면, 동일한 리터럴 값은 단일 객체로 통합될 수 있습니다.

작은 정수 풀 (Small Integer Cache)

CPython은 성능 향상을 위해 자주 사용되는 정수값을 미리 생성하여 캐싱합니다. 이 범위는 일반적으로 -5부터 256까지입니다. 이 범위 내의 정수를 생성할 때마다 새로운 객체를 만들지 않고, 기존 캐시된 객체를 참조하게 됩니다.

print((-5 is -5))  # True
print((256 is 256)) # True
print((257 is 257)) # False (항상 그런 것은 아니며, 최적화 여부에 따라 달라짐)

257 이상의 정수는 기본적으로 별도의 객체로 간주되지만, 컴파일 단계에서 리터럴이 동일하고 동일한 코드 블록 내에 있다면 파이썬이 이를 최적화해 동일 객체를 참조할 수도 있습니다.

문자열 인터닝 (String Interning)

파이썬은 특정 조건을 만족하는 문자열도 자동으로 "인터닝"하여 중복 생성을 방지합니다. 인터닝이란, 동일한 값을 가진 문자열이 하나의 메모리 객체만을 공유하도록 하는 기술입니다.

  • 길이가 0 또는 1인 문자열: 항상 인터닝됩니다.
  • 식별자 형식의 문자열: 알파벳, 숫자, 언더스코어만 포함하고, 변수명처럼 보이는 문자열은 인터닝됩니다.
    예: "hello_world_1", "var2"
  • 곱셈 연산으로 생성된 문자열:
    • 곱하는 수가 1이고, 구성 문자가 알파벳/숫자/언더스코어인 경우 인터닝됨.
    • 곱하는 수가 1 초과이고, 결과 문자열 길이가 20자를 넘지 않으며, 구성 문자가 제한된 경우 인터닝 가능.
  • 불리언 값: TrueFalse는 항상 동일한 싱글톤 객체입니다.
s1 = "test"
s2 = "test"
print(s1 is s2)  # True (자동 인터닝)

s3 = "hello!"
s4 = "hello!"
print(s3 is s4)  # 문자 '!' 포함, 조건 불일치 시 False일 수 있음

수동 인터닝 강제 적용

임의의 문자열을 강제로 인터닝하려면 sys.intern() 함수를 사용할 수 있습니다. 이는 메모리 효율성과 비교 속도 향상을 위해 특히 많은 양의 반복 문자열을 처리할 때 유용합니다.

import sys

a = sys.intern("very_long_string_that_repeats")
b = sys.intern("very_long_string_that_repeats")
print(a is b)  # 반드시 True

최적화의 장단점

장점:

  • 빈번하게 사용되는 값에 대해 객체 생성 및 삭제 오버헤드 감소
  • 메모리 사용량 절감
  • is 연산자 기반의 빠른 동등성 비교 가능

단점:

  • 초기 인터닝 과정에서 해시 계산 및 조회로 인해 약간의 성능 저하 발생 가능
  • 개발자가 예상하지 못한 동작(is 사용 시) 유발 가능 → 권장: 값 비교는 ==, 객체 동일성 확인은 의도가 명확할 때만 is 사용

태그: 파이썬 객체 최적화 정수 캐싱 문자열 인터닝 sys.intern

5월 31일 10:33에 게시됨