Python, descriptor에 대하여

김어진·2021년 1월 18일
1

python

목록 보기
1/2

디스크립터


디스크립터란?

descriptor란 __get__나 __set__, __delete__ 등의 magic method가 구현되어 있는 객체를 의미한다. descriptor는 다른 객체의 속성으로써 존재할 때, 그 속성에 대하여 읽기, 쓰기, 삭제 등의 동작을 할때, 동작에 따라 각 구현된 method가 호출되는 객체이다.

그니까...

object a가 있고 attribute로 b라는게 있다고 하면. a.b로 b를 조회할 수 있음 ㅇㅇ.
이게 일반적인 상황이면 a의 dict에서(물론 __slots__가 구현되어 있으면 딕셔너리 아님) b를 찾아서 조회하는데 만약 b가 descriptor object면 b의 __get__이 실행되는 것임

그럼 이건 어따가 씀

그 classmethod나 staticmethod, property 등을 구현할 때 쓰임.
알아두면 python에 대한 insight가 조금 증가하는 느낌이 든다. ㅎㅎ

종류

descriptor는 3가지 프로토콜이 있다. 이미 위에서 설명한 dunder가 붙은 get, set, delete이다. 이들 중 어떤 것이 구현되어 있느냐에 따라서 다른 용도로 쓰인다.

만약 get만 구현 시, 비 데이터 디스크립터이고.
set과 delete를 구현시 데이터 디스크립터이다.

디스크립터 구현해보기

간단한 property와 비슷한 동작을 하는 디스크립터를 구현해보자!

class MyProperty():
    def __init__(self, getter=None, setter=None, deleter=None):
        self.getter = getter
        self.setter = setter
        self.deleter = deleter

    def __get__(self, instance, owner=None):
        if self.getter is None:
            raise AttributeError
        
        print('get egg')
        return self.getter(instance)

    def __set__(self, instance, value):
        if self.setter is None:
            raise AttributeError

        print(f'set egg to {value}') 
        return self.setter(instance, value)

    def __delete__(self, instance):
        if self.deleter is None:
            raise AttributeError

        return self.deleter(instance)

생성 시에 getter, setter, deleter를 인자로 받고 저장한 뒤, 각각 동작에 따라 init때 받은 함수를 호출해주는 디스크립터를 구현했따.

    def __init__(self):
        self.egg = 0 

    def get_egg(self):
        return self._egg

    def set_egg(self, value):
        self._egg = value

    def delete_egg(self):
        del(self._egg)

    egg = MyProperty(getter=get_egg, setter=set_egg, deleter=delete_egg)

위와 같이 다른 한 class의 속성으로써 디스크립터 객체를 놓고. 아래의 코드를 실행하면

my_egg = Egg()
print(my_egg.egg)
my_egg.egg = 10
print(my_egg.egg)

아래와 같이 디스크립터에 선언한 메소드가 실행되었음을 알 수 있다.

set egg to 0
get egg
0
set egg to 10
get egg
10

요약

그니까 디스크립터는 어... 속성의 읽기 쓰기 삭제를 개발자가 커스텀할 수 있게 해주는 객체...?

0개의 댓글