Programming,  Python

[Python] Property Extension

deleter

지난번에 Python에서 접근 지정을 위해 property class를 사용한다고 배웠다. Property 기능은 크게 세 가지가 존재하는데, getter, setter, deleter가 존재한다.

deleter는 property를 삭제할 때 호출되는 함수다. (del을 통해)

Subclass에서 Property

class Person:
    def __init__(self, name):
        self.name = name # 실제 호출은 setter property가 호출됨
                       # 따라서 name의 저장은 self._name 에 저장됨
    @property
    def name(self):
        return self._name
    # name = property(name)

    @name.setter
    def name(self, value):
        if not isinstance(value, str):
            raise TypeError('Expected a string')
        self._name = value

    @name.deleter
    def name(self):
        raise AttributeError("Can't delete attribute")

class SubPerson(Person):
    @property
    def name(self):
        print('Getting name')
        return super().name

    @name.setter
    def name(self, value):
        print('Setting name to', value)
        super(SubPerson, SubPerson).name.__set__(self, value)

    @name.deleter
    def name(self):
        print('Deleting name')
        super(SubPerson, SubPerson).name.__delete__(self)

if __name__ == '__main__':
   a = SubPerson('Guido')
   print(a.name)
   a.name = 'Dave'
   print(a.name)
   try:
       a.name = 42
   except TypeError as e:
       print(e)
Setting name to Guido
Getting name
Guido
Setting name to Dave
Getting name
Dave
Setting name to 42
Expected a string

Subclass에서 super class의 멤버를 호출하기 위해서 super의 getter, setter를 호출하면 된다. 참고로 __set____delete__는 super class의 setterdeleter를 각각 호출한다.

super(SubPerson, SubPerson).name.__set__(self, value) 에서 super()의 인자는 다음과 같다.

super([Subclass Name], [Subclass Type] or [Subclass Instance Type])

실제 우리가 접근하고자 하는 getter와 setter는 모두 instance 변수 (self.* 가 붙는 형식)가 아닌 class 변수 (self.* 가 붙지 않는 형식) 이다. 만약 instance type이면 생략이 가능하다.
위 코드에선 super().name 으로 name이 class 변수기 때문에 super()의 두 번째 인자는 class type (SubPerson)이 들어가야한다.

부모의 메소드에 도달하기 위한 유일한 방법은 instance 변수가 아닌 class 변수로 접근해야 한다.

Leave a Reply

Your email address will not be published. Required fields are marked *