Descriptor

EBAB!·2024년 1월 21일
0

객체의 속성에 대한 접근을 제어하는 메커니즘을 뜻한다. 기본적으로 디스크립터는 클래스의 속성에 대한 접근을 커스텀하게 제어할 수 있는 특별한 종류의 객체이다. 디스크립터를 통해서 개발자는 속성에 접근하거나 속성을 설정할 때 특정 코드를 자동으로 실행시킬 수 있다.

Discriptor Magic Method

디스크립터 클래스는 3개의 매직 메서드를 가지고
각 메서드는 공통적으로 self, obj 파라미터를 가진다.

  • self: 디스크립터 클래스를 가리키는 파라미터
  • obj: 디스크립터가 사용되는 객체(클래스)를 가리키는 파라미터

__get__(self, obj, type=None): 속성에 접근할 때 실행. type은 오브젝트의 타입을 말한다.

__set__(self, obj, value): 속성을 새 value 값으로 설정할 때 실행.
__delete__(self, obj): 속성을 삭제할 때 실행.

class DescriptorEx1(object): 
  
    def __init__(self, name = 'Default'): 
        self.name = name 
  
    def __get__(self, obj, objtype): 
        return "Get method called. -> self : {}, obj : {}, objtype : {}, name : {}".format(self, obj, objtype, self.name) 
  
    def __set__(self, obj, name): 
        print('Set method called.')
        if isinstance(name, str): 
            self.name = name 
        else: 
            raise TypeError("Name should be string") 

    def __delete__(self, obj):
        print('Delete method called.')
        self.name = None
        
class Sample1(object): 
    name = DescriptorEx1()
    
s1 = Sample1() 

# __set__ 호출 
s1.name = "Descriptor Test1"

# s1.name = 7  # 예외 발생

# attr 확인
# __get__ 호출
print(s1.name)  # Get method called. -> self : <__main__.DescriptorEx1 object at 0x000001E0A5EC1390>, obj : <__main__.Sample1 object at 0x000001E0A5EC1BA8>, objtype : <class '__main__.Sample1'>, name : Descriptor Test1

# __delete__ 호출
del s1.name

# 재확인
# __get__ 호출
print(s1.name)  # Get method called. -> self : <__main__.DescriptorEx1 object at 0x000001E0A5EC1390>, obj : <__main__.Sample1 object at 0x000001E0A5EC1BA8>, objtype : <class '__main__.Sample1'>, name : None

property

property를 이용한 디스크립터 작성 방식도 있다.

참고

class property(fget=None, fset=None, fdel=None, doc=None)

class DescriptorEx2(object): 
  
    def __init__(self, value): 
        self._name = value 
  
    def getVal(self): 
        return "Get method called. -> self : {}, name : {}".format(self, self._name) 
  
    def setVal(self, value): 
        print('Set method called.')
        if isinstance(value, str): 
            self._name = value
        else: 
            raise TypeError("Name should be string") 

    def delVal(self):
        print('Delete method called.')
        self._name = None

    name = property(getVal, setVal, delVal, 'Property Method Example.')
profile
공부!

0개의 댓글