Programming Language/Python

Effective Python. @property, @{property}.setter 사용

알파해커 테크노트 2021. 3. 2. 00:22
반응형

보통 자바와 같은 언어에 익숙한 사람이라면, 아래와 같이 getter / setter 함수에 익숙할 것이다.

class OldResistor:
	def __init__(self, ohms):
    	self._ohms = ohms
        
    def get_ohms(self):
    	return self._ohms
        
    def set_ohms(self, ohms):
    	self._ohms = ohms

 

이렇게 setter와 getter를 사용하는 것은 다음과 같이 사용할 수 있다.

r0 = OldResistor(50e3)
r0.set_ohms(10e3)
r3.set_ohms(r0.get_ohms() + 5e3)

 

간단하고, 클래스의 인터페이스를 정의하는데 도움이 되고, 사용법을 검증할 수 있게 하고, 경계를 정의하기 쉽게 해준다.

그러나 파이썬 답지 않다.

 

아마 아래와 같이 쓸 수 있으면, 좀 더 심플하고, 명확하고, 따라서 파이썬다워 질 것 같다.

(setter, getter를 쓰지 않고, 해당 속성에 직접 접근)

r1 = Resistor(50e3)
r1.ohms = 10e3
r1.ohms += 5e3

 

만약 setter, getter에서 사용법을 검증하는 것과 같이, 속성을 설정할 때 (혹은 읽어올 때) 특별한 동작이 일어나야 한다면,

@property 데코레이터와 이에 대응하는 setter 속성을 사용하면 된다.

class NewResistor:
	def __init__(self, ohms):
    	self._ohms = ohms
        
    @property
    def ohms(self):
    	return self._ohms
        
    @ohms.setter
    def ohms(self, ohms):
    	if ohms <= 0:
        	raise ValueError(f'{ohms} ohms must be > 0')
    	self._ohms = ohms

 


 

참고로, 속성을 불변(immutable)으로 만들 때도 @property를 사용할 수 있다.

class FixedResistor:
	def __init__(self, ohms):
    	self._ohms = ohms
        
    @property
    def ohms(self):
    	return self._ohms
        
    @ohms.setter
    def ohms(self, ohms):
    	if hasattr(self, ohms):
        	raise AttributeError("Can't set attribute")
    	self._ohms = ohms

 

해당 객체를 생성하고 나서 속성에 새로운 값을 할당하려고 하면 예외가 일어날 것이다.

r2 = FixedResistor(1e3)
r2.ohms = 2e3

>>>
AttributeError: Can't set attribute

 

반응형