파이썬의 @foo.setter가 왜 나에게 효과가 없습니까?
-
11-09-2019 - |
문제
그래서 저는 Python 2.6에서 데코레이터를 가지고 놀고 있으며, 일을하는 데 어려움을 겪고 있습니다. 내 수업 파일은 다음과 같습니다.
class testDec:
@property
def x(self):
print 'called getter'
return self._x
@x.setter
def x(self, value):
print 'called setter'
self._x = value
내가 생각한 것은 치료하는 것입니다 x
속성과 마찬가지로이 기능을 Get and Set에서 호출하십시오. 그래서 나는 유휴 상태를 발사하고 확인했습니다.
>>> from testDec import testDec
from testDec import testDec
>>> t = testDec()
t = testDec()
>>> t.x
t.x
called getter
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "testDec.py", line 18, in x
return self._x
AttributeError: testDec instance has no attribute '_x'
>>> t.x = 5
t.x = 5
>>> t.x
t.x
5
분명히 첫 번째 호출은 Getter를 호출하기 때문에 예상대로 작동하며 기본값이 없으며 실패합니다. 좋아, 좋아, 이해한다. 그러나 할당 요청 t.x = 5
새로운 재산을 만드는 것 같습니다 x
, 그리고 이제 Getter가 작동하지 않습니다!
내가 무엇을 놓치고 있습니까?
해결책
당신은 사용중인 것 같습니다 고전적인 구식 수업 Python 2에서 속성 올바르게 작동하려면 사용해야합니다 새로운 스타일의 수업 대신 (Python 2에서는 당신이해야합니다 상속 object
). 수업을 그냥 선언하십시오 MyClass(object)
:
class testDec(object):
@property
def x(self):
print 'called getter'
return self._x
@x.setter
def x(self, value):
print 'called setter'
self._x = value
효과가있다:
>>> k = testDec()
>>> k.x
called getter
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/devel/class_test.py", line 6, in x
return self._x
AttributeError: 'testDec' object has no attribute '_x'
>>> k.x = 5
called setter
>>> k.x
called getter
5
>>>
문제를 일으킬 수있는 또 다른 세부 사항은 두 방법 모두 재산이 작동하려면 동일한 이름이 필요하다는 것입니다. 이와 같은 다른 이름으로 세터를 정의하면 작동하지 않습니다.:
@x.setter
def x_setter(self, value):
...
그리고 처음에는 완전히 쉽게 찾을 수없는 한 가지는 순서입니다 : The Getter 먼저 정의해야합니다. 세터를 먼저 정의하면 얻을 수 있습니다 name 'x' is not defined
오류.
다른 팁
이 예외를 찾고있는 다른 사람들을위한 메모입니다. 두 기능 모두 같은 이름이 필요합니다. 다음과 같이 메소드의 이름을 지정하면 예외가 발생합니다.
@property
def x(self): pass
@x.setter
def x_setter(self, value): pass
대신 두 가지 메소드에 동일한 이름을 부여하십시오
@property
def x(self): pass
@x.setter
def x(self, value): pass
또한 선언의 순서가 중요하다는 점에 유의해야합니다. getter는 파일의 세터 전에 정의해야합니다. 그렇지 않으면 NameError: name 'x' is not defined
객체에서 수업을 도출하여 수행하는 새로운 스타일 클래스를 사용해야합니다.
class testDec(object):
....
그런 다음 작동해야합니다.
누군가 Google에서 여기에 오면 위의 답변 외에도 Setter를 호출 할 때주의를 기울여야한다고 덧붙이고 싶습니다. __init__
당신의 수업의 방법을 기반으로합니다 이 답변구체적으로:
class testDec(object):
def __init__(self, value):
print 'We are in __init__'
self.x = value # Will call the setter. Note just x here
#self._x = value # Will not call the setter
@property
def x(self):
print 'called getter'
return self._x # Note the _x here
@x.setter
def x(self, value):
print 'called setter'
self._x = value # Note the _x here
t = testDec(17)
print t.x
Output:
We are in __init__
called setter
called getter
17