4

"in-place operator"재정의 (예 : +=)와 첫 번째 인스턴스를 @property을 통해 노출하는 두 가지 클래스가 있습니다. (참고 :이 크게 문제가 재생 최소 내 실제 코드에서 간단입니다.)읽기 전용 속성을 변경할 수있게하려면 어떻게해야합니까?

class MyValue(object): 
    def __init__(self, value): 
     self.value = value 

    def __iadd__(self, other): 
     self.value += other 
     return self 

    def __repr__(self): 
     return str(self.value) 

class MyOwner(object): 
    def __init__(self): 
     self._what = MyValue(40) 

    @property 
    def what(self): 
     return self._what 

지금, 나는이 노출 된 재산이 연산자를 사용하려고하면

>>> owner = MyOwner() 
>>> owner.what += 2 
AttributeError: can't set attribute 

내가 찾은 바에 따르면이 속성은 owner에 설정하려고하기 때문에 예상됩니다. 으로 설정하는 것을 방지 할 수있는 방법이 있습니까? (내부에서) 수정하려면 개체를 수정 하시거나 그냥 언어의 단점입니까?


(결국 내가 파이썬 3. 작업하려는 때문에 내가은 이전 스타일의 클래스에 복귀하지 않고 바람직 , 다른 길을 갈려고도 this question을 볼 수 있지만) 그동안 나는 같은 일을하는 방법으로이 문제를 해결했습니다.

class MyValue(object): 
    # ... 

    def add(self, other): 
     self.value += other 

>>> owner = MyOwner() 
>>> owner.what.add(2) 
>>> print(owner.what) 
42 
+1

다른 해결 방법 :'온도 = owner.what; temp + = 2', [owner.what] [0] + = 2'로 표시됩니다. –

+0

사용자 코드에서 "hackish"부분을 지키고 싶습니다. 그래서 @ Martijn의 대답으로 갈 것이지만, 아이디어에 감사드립니다. 그들은 다른 것들을 위해 유용 할 수 있습니다. 나는 그들이 매우 간결하다는 것을 좋아한다 (특히 두 번째 :). – criptych

답변

5

이것은 언어의 단점입니다. 모든 개체를 변경할 수 있기 때문에

object = object.__iadd__(value) 

이 필요합니다 다음 object += value 작업이에 변환합니다. 너의 것이고 정확하게 위의 작업의 할당 부분에 대해 가상 no-op가되는 self을 반환합니다. 귀하의 경우에는

이 문제의 object가 속성이므로 다음이 실행됩니다

owner.what = owner.what.__iadd__(2) 

을 제외하고 왼쪽에 여기 object.what를 참조 피하는에서 (tmp = owner.what; tmp += 2를 등)이있는 이것을 깨끗하게 처리하는 방법.

당신은 쉽게 속성에 할당이에 동일한 개체 및 게이트에 관한 것을 감지 할 수 있습니다

class MyOwner(object): 
    def __init__(self): 
     self._what = MyValue(40) 

    @property 
    def what(self): 
     return self._what 

    @what.setter 
    def what(self, newwhat): 
     if newwhat is not self._what: 
      raise AttributeError("can't set attribute") 
     # ignore the remainder; the object is still the same 
     # object *anyway*, so no actual assignment is needed 

데모 :

>>> owner = MyOwner() 
>>> owner.what 
40 
>>> owner.what = 42 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<string>", line 24, in what 
AttributeError: can't set attribute 
>>> owner.what += 2 
>>> owner.what 
42 
+0

"이것은 언어의 버릇입니다." 나는 그것을 두려워했다. 나는 너의 제안을 감사 할께. 고마워. – criptych

관련 문제