-
파이썬 프러퍼티 사용하여 일관되게 속성에 접근하라Programmer/Programming 2018. 1. 17. 11:56
파이썬의 프러퍼티(property)를 설명한 책과 글은 많음으로 필요성만 살짝 언급하고 지나가겠다.
파이썬에서는 공개 애트리뷰트(public attribute)을 직접 접근(access)하는 것이 관례이다.
class A: def __init__(self): self.x = 0 a = A() a.x = 1 print('{}'.format(a.x))
그런데, 비공개(private) 애트리뷰트가 필요한 경우가 있다. 1
이들을 외부에서 접근하기 위해서는 엑세스 함수-예를 들면, get_xxx(), set_xxx()와 같은 것-을 사용해야 한다.
문제는 접근 형식이 관례와 달라지는데 있다.
즉, 애트리뷰트가 공개인지 비공개인지 일일이 신경써야 한다. 2
이럴 때, 프러퍼티를 사용하면 동일한 표현 형식으로 접근이 가능하다.아래는 공개/비공개 속성을 동일하게 접근하는 샘플코드이다.
class A: def __init__(self): self.x = 0 self.__y = 0 @property def y(self): return self.__y @y.setter def y(self, value): self.__y = value a = A() # attribute access a.x = 1 print('{}'.format(a.x)) # property access a.y = 2 print('{}'.format(a.y))
위 예제는 공개/비공개 애트리뷰트를 동일하게, 'a.x', 'a.y'로 접근한다.
위 예제와 비교하기 위해서 비공개 속성을 엑세스 함수로 사용하도록 구현해봤다.
class A: def __init__(self): self.x = 0 self.__y = 0 def get_y(self): return self.__y def set_y(self, value): self.__y = value a = A() # attribute access a.x = 1 print('{}'.format(a.x)) # getter/setter access a.set_y(2) print('{}'.format(a.get_y()))
매번 주의를 기울여, 어떤 것은 직접 접근 'a.x'로 다른 것은 액세스 함수 'a.set_y()'로 사용하도록 신경써야 한다.
비일관성은 주의력을 소진하게 만들어 좋지 않다.매우 드물기는 하지만, 엑세스 함수의 오버라이딩(overriding)이 필요할 때가 있다.
그러한 경우, 아래 예제 코드를 참고하여 작성하도록 한다. 3class A: def __init__(self): pass @property def x(self): return self.__x @x.setter def x(self, value): self.__x = value class B(A): def __init__(self): super().__init__() @A.x.setter def x(self, value): if value < 0: raise ValueError('x below 0 is not possible') super(B, B).x.__set__(self, value) class C(B): def __init__(self): super().__init__() @B.x.setter def x(self, value): if value > 100: raise ValueError('x above 100 is not possible') super(C, C).x.__set__(self, value)
데코레이션 패턴(decoration pattern)이 상속보다 더 유용할 수 있다.
예를 들면, getter에 캐싱 기능을 추가하는 경우가 그러하다.
데코레이션 패턴으로 구현하는 것은 본 글의 취지와 맞지 않아서 생략한다.참고 링크:
'Programmer > Programming' 카테고리의 다른 글
러스트와 다른 언어의 멀티라인 처리 비교 (0) 2019.02.12 러스트에서 문자열을 효과적으로 연결하기 (1) 2019.02.08 기본 값(default value)을 언제 사용할까? (0) 2018.01.02 C++에서 언제 어떻게 struct를 사용하는가? (4) 2017.09.25 일단 만들어라. 두 번 만들어라. 그러면 보일 것이다. (0) 2017.06.29 댓글