@property
은 게터를 정의하는 좋은 방법입니다. 속성이 변경 가능하면 반환 된 참조를 사용하여 클래스 정의로 제어되지 않는 방식으로 속성을 수정할 수 있습니다. 동기 부여 비유로 바나나 스탠드를 사용 하겠지만이 문제는 컨테이너를 래핑하는 모든 클래스에 적용됩니다.클래스 속성을 변경하지 못하게하려면 어떻게해야합니까?
class BananaStand:
def __init__(self):
self._money = 0
self._bananas = ['b1', 'b2']
@property
def bananas(self):
return self._bananas
def buy_bananas(self, money):
change = money
basket = []
while change >= 1 and self._bananas:
change -= 1
basket.append(self._bananas.pop())
self._money += 1
return change, basket
바나나 스탠드 방문객들이 바나나를 지불하고 싶습니다. 불행히도, 내 바나나 중 하나를 복용에서 원숭이를 (누가 더 잘 모르는) 멈추는 아무것도. 원숭이는 내부 특성 인 _banana
을 사용할 필요가 없었으며, 지불하지 않고 바나나를 가져 왔습니다.
def take_banana(banana_stand):
return banana_stand.bananas.pop()
>>> stand = BananaStand()
>>> stand.bananas
['b1', 'b2']
>>> take_banana(stand)
'b2'
>>> stand.bananas
['b1']
이 비유가 좀 바보이지만, 변경 가능한 속성이있는 클래스는 우발적 인 파괴 행위로부터 보호되지 않습니다. 내 실제 경우에는 동일한 길이를 유지해야하는 두 개의 배열 특성이있는 클래스가 있습니다.
>>> from array import array
>>> x = array('f', [1,2,3])
>>> x
array('f', [1.0, 2.0, 3.0])
>>> x[1:2] = array('f', [4,5,6])
>>> x
array('f', [1.0, 4.0, 5.0, 6.0, 3.0])
배열 속성 인 경우에 동일한 behavour가 발생 어레이와, 제 1 및 자동 불변 내 동일한 크기 파괴에 제 2 어레이를 배분하고에서 사용자를 막는 것도 없다.
나는 피하는 문제의 두 가지 방법을 생각할 수 있습니다
- 서브 클래스 배열과
__setitem__
우선합니다. 나는이 배열 접합 동작을 내부적으로 사용할 수 있기를 원하기 때문에 이에 저항한다. - 접근자를 변경하여 배열의 deepcopy를 반환하십시오. 반환 된 배열은 여전히 변경할 수 있지만 변경된 배열은 부모 개체에 영향을주지 않습니다.
이 문제를 해결하려면 우아한 방법이 있습니까? 저는 속성을 하위 클래스 화하는 멋진 방법에 특히 관심이 있습니다.