__slots__는 클래스의 특별한 속성으로, 인스턴스의 허용 속성 집합을 제한하고, 메모리를 절약하며, 속성 접근 속도를 높여줍니다. __slots__의 사용은 특히 대량의 유사 객체에 유용합니다.
문제의 역사:
__slots__의 등장은 기본적으로 각 Python 객체 인스턴스에 속성 딕셔너리(__dict__)가 존재함에 따라 발생합니다. 이는 편리하지만 메모리 측면에서 비용이 많이 듭니다. 적은 수의 필드로 백만 개의 객체에 대해 상당한 오버헤드가 발생합니다.
문제:
일반 클래스 인스턴스는 동적으로 확장될 수 있어 편리하지만 비효율적입니다. __slots__의 사용은 새로운 속성의 동적 추가를 제한하고, 인스턴스 속성 딕셔너리를 제거하여 메모리를 절약하고 접근 속도를 향상시킵니다.
해결책:
__slots__ 속성에 허용된 필드 목록을 명시해야 합니다:
class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y p = Point(1, 2) p.z = 3 # AttributeError: 'Point' 객체에 'z' 속성이 없습니다.
주요 특징:
__slots__가 있는 클래스 인스턴스를 생성한 후 목록에 없는 속성을 추가할 수 있습니까?
아니요. __slots__ 목록에 없는 속성을 추가하려고 하면 AttributeError가 발생합니다. 이는 객체의 확장성에 대한 제한을 부과합니다.
__slots__가 있는 클래스를 상속받아 새로운 필드를 추가할 수 있습니까?
네, 그러나 각 자식 클래스는 자신의 __slots__를 선언해야 합니다. 부모와 현재 __slots__는 결합됩니다. 단, 자식 클래스에서 __slots__를 선언하지 않으면 자식에게 다시 __dict__가 생깁니다!
__slots__는 변경 불가능(immutable) 유형에 대해 작동합니까?
네, 하지만 슬롯 객체를 변경 불가능하게 만들기 위한 추가 조치를 구현해야 합니다 (예: 세터 없는 property를 통해).
점에 대한 일반 클래스:
class Point: def __init__(self, x, y): self.x = x self.y = y points = [Point(i, i) for i in range(1_000_000)]
장점:
단점:
슬롯이 있는 유사한 클래스:
class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y points = [Point(i, i) for i in range(1_000_000)]
장점:
단점: