문제
클래스로 인스턴스를 많이 생성할 때, 메모리도 같이 증가하여 자원을 효율적으로 쓰지 못한다.
해결
클래스 속성으로 __slots__ 필드를 튜플 혹은 리스트로 생성하여,
생성자가 가지고 있어야 하는 속성으로만 제한하여 메모리를 줄일 수 있다.
자료구조 상 딕셔너리는 해시 테이블을 생성을 위한 메모리를 잡아놓기 때문에,
튜플과 리스트에 비해 메모리를 많이 가지고 있다.
코드
slots를 만들어주면 더 이상 해당 클래스는 slots에 정의된 변수밖에 생성하지 못한다.
반면, dictionary는 클래스의 속성을 유동적으로 추가할 수 있다.
즉, immutable한 클래스에 대해서만 slots을 정의하여 사용하는 것이 좋다.
import sys
class WithoutSlots:
def __init__(self, x, y):
self.x = x
self.y = y
class WithSlots:
__slots__ = ('x', 'y')
def __init__(self, x, y):
self.x = x
self.y = y
a = WithoutSlots(1, 2)
b = WithSlots(1, 2)
print(sys.getsizeof(a.__dict__)) # 296 bytes
print(sys.getsizeof(b)) # 48 bytes
뭐가 좋은가?
메모리를 최적화 할 수 있다.
1. 반복적이고 불변한 인스턴스를 많이 만들어야 할 때 (ex. 날짜 클래스의 년,월,일)
2. 클래스의 변수에 제약을 두고 싶을 때
# 데이터 모델의 변수 제한
from dataclasses import dataclass
@dataclass
class WithoutSlots:
x: int
y: int
@dataclass(slots=True) # ✅ slots=True로 메모리 절약 가능
class WithSlots:
x: int
y: int
a = WithoutSlots(1, 2)
b = WithSlots(1, 2)
a.z = 3 # Pass
b.z = 3 # AttributeError: 'WithSlots' object has no attribute 'z'
출처: Beazley, D., & Jones, B. K. (2013). *Python cookbook* (3rd ed., pp. 227–230). O’Reilly Media