새로운 클래스 인터페이스를 정의할 때는 간단한 공개 애트리뷰트에서 시작하고, 세터나 게터 메서드를 가급적 사용하지 말라
객체에 있는 애트리뷰트에 접근할 때 특별한 동작이 필요하면 @property로 이를 구현
@property 메서드를 만들 때는 최소 놀람의 법칙을 따르고 이상한 부작용 만들지 말기
@property 메서드가 빠르게 실행되도록 유지
#클래스에 게터나 세터 메서드 정의
#장점: 캡슐화 가능, 필드 사용 검증, 경계 설정 쉬워짐
#그러나 파이썬 답진 않다
class OldResistor:
def __init__(self, ohms):
self._ohms = ohms
def get_ohms(self):
return self._ohms
def set_ohms(self, ohms):
self._ohms = ohms
#명시적으로 세터와 게터를 말할 필요가 없다
class Resistor:
def __init__(self, ohms):
self.ohms = ohms
self.voltage = 0
self.current = 0
r1 = Resistor(50e3)
r1.ohms = 10e3
r1.ohms += 5e3 #필드 제자리 증가 쉬움
r1
<__main__.Resistor at 0x7fca060491d0>
#애트리뷰트 설정 시 특별 기능 수행
#애트리뷰트를 @property 데코레이터 사용
"""
1.setter 애트리뷰트 옮기기
2.새 하위 클래스 만든다.
3.Registor에서 voltage프로퍼터 값 대입
4. current값 변화
5. 세터와 게터의 이름이 우리가 의도한 프로퍼티 이름과 일치
"""
class VoltageResistance(Resistor):
def __init__(self, ohms):
super().__init__(ohms)
self._voltage = 0
@property
def voltage(self):
return self._voltage
@voltage.setter
def voltage(self, voltage):
self._voltage = voltage
self.current = self._voltage / self.ohms
#세터 메서드가 호출되고, 이 메서드는 객체의 current 애트리뷰트를 변경된 전압 값 갱신
#setter지정하면 타입 검사나 클래스 값 검증 가능
class BoundedResistance(Resistor):
def __init__(self, ohms):
super().__init__(ohms)
@property
def ohms(self):
return self.ohms
@ohms.setter
def ohms(self, ohms):
if ohms <= 0 :
raise ValueError(f' 저항 > 0이어야 합니다. 실제 값: {ohms}')
self._ohms = ohms
# '@property 메서드를 활용하여 게터나 세터 구현이 예기치 않은 동작 실행 안함
class MysteriousResistor(Resistor):
@property
def ohms(self):
self.voltage = self._ohms *self.current
return self._ohms
@ohms.setter
def ohms(self, ohms):
self._ohms = ohms