PHpullh
학습 라이브러리/Python/descriptor 프로토콜

PYTHON · 객체지향

descriptor 프로토콜

디스크립터 프로토콜(__get__, __set__, __delete__)로 속성 접근을 완전히 커스터마이징합니다.

객체지향고급descriptor디스크립터__get____set__

핵심 설명

디스크립터 프로토콜(__get__, __set__, __delete__)로 속성 접근을 완전히 커스터마이징합니다.

Python code

class Validated:
    """재사용 가능한 검증 디스크립터"""
    def __init__(self, min_val=None, max_val=None):
        self.min_val = min_val
        self.max_val = max_val

    def __set_name__(self, owner, name):
        self.name = name
        self.storage_name = f"_desc_{name}"

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return getattr(obj, self.storage_name, None)

    def __set__(self, obj, value):
        if self.min_val is not None and value < self.min_val:
            raise ValueError(f"{self.name}: {value} < 최소값 {self.min_val}")
        if self.max_val is not None and value > self.max_val:
            raise ValueError(f"{self.name}: {value} > 최대값 {self.max_val}")
        setattr(obj, self.storage_name, value)

class Product:
    price = Validated(min_val=0)
    quantity = Validated(min_val=0, max_val=10000)

    def __init__(self, name, price, quantity):
        self.name = name
        self.price = price
        self.quantity = quantity

p = Product("노트북", 1500000, 50)
print(f"{p.name}: {p.price:,}원 x {p.quantity}")
# p.price = -100  # ValueError!

학습 팁

__set_name__(Python 3.6+)으로 디스크립터가 속성명을 자동으로 알 수 있어 코드가 간결해집니다.

주의할 점

디스크립터를 인스턴스 변수로 선언하면 동작하지 않습니다. 반드시 클래스 변수로 선언해야 합니다.

자주 묻는 질문

descriptor 프로토콜란 무엇인가요?

디스크립터 프로토콜( __get__ , __set__ , __delete__ )로 속성 접근을 완전히 커스터마이징합니다.

descriptor 프로토콜 학습 시 주의할 점은 무엇인가요?

디스크립터를 인스턴스 변수로 선언하면 동작하지 않습니다. 반드시 클래스 변수로 선언해야 합니다.