디스크립터 Descripter

  1. 객체에서 서로 다른 객체를 속성 값으로 가지는 것.
  2. Read, Write, Delete 등을 미리 정의 가능
  3. data descriptor(set, del), non-data descriptor(get)
  4. 읽기 전용 객체 생성 장점, 클래스를 의도하는 방향으로 생성 가능

Descriptor 예제

기본

# Ex1
# 기본적인 Descriptor 예체

class DescriptorEx1(object):
    def __init__(self, name='Default'):
        self.name = name

    def __get__(self, instance, owner):
        return 'Get method called. -> self : {}, obj : {}, objtype : {}, name : {}'.format(
            self, instance, owner, self.name
        )

    def __set__(self, instance, value):
        print('Set method called.')
        if isinstance(value, str): # 문자열인지 확인해주고
            self.name = value
        else:
            raise TypeError('Name should be string.')

    def __delete__(self, instance):
        print('Delete method called.')
        self.name = None

class Sample1:
    name = DescriptorEx1()

s1 = Sample1()
s1.name = 'Descriptor Test1' # 이 단계에서 __set__을 처리해준다. 그래서 Set method called가 된다.

#예외 호출
# s1.name = 10

# attr 확인
# __get__ 호출
print('Ex1 > ', s1.name)
# del s1.name

값을 하나씩 가져온다. 그리고 이렇게 호출을 하게 된다. 지울떄는 지워지는 것을 가져오게 될 것이다.

Property 클래스 사용해서 Descriptor 직접 구현

# Ex2
# Property 클래스 사용 Descriptor 직접 구현
# 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 테스트를 하는 name 필드입니다. 의미 없습니다.')

# 최초 값 확인
s2 = DescriptorEx2('Descriptor Test2')

print('Ex2 > ', s2.name)

# setVal 호출
s2.name = 'Descript Test2 Method'

# 예외 발생
# s2.name = 10

# getVal 호출
print('Ex2 > ', s2.name)

# delVal 호출
del s2.name

print('Ex2 > ', s2.name)

# Doc 확인
print('Ex2 > ', DescriptorEx2.name.__doc__)

정말 유명한 코딩은 이런 식으로 코딩을 할 수 있습니다.