Więc bawię się dekoratorami w Pythonie 2.6 i mam problemy z ich uruchomieniem. Oto plik mojej klasy:
class testDec:
@property
def x(self):
print 'called getter'
return self._x
@x.setter
def x(self, value):
print 'called setter'
self._x = value
Pomyślałem, że oznaczało to traktowanie x
jak właściwość, ale wywołanie tych funkcji podczas pobierania i ustawiania. Tak więc odpaliłem IDLE i sprawdziłem:
>>> 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
Oczywiście pierwsze wywołanie działa zgodnie z oczekiwaniami, ponieważ wywołuję getter i nie ma wartości domyślnej i kończy się niepowodzeniem. OK, dobrze, rozumiem. Jednak wywołanie przypisania t.x = 5
wydaje się tworzyć nową właściwość x
, a teraz funkcja pobierająca nie działa!
czego mi brakuje?
Odpowiedzi:
Wydaje się, że używasz klasycznych klas w starym stylu w Pythonie 2. Aby właściwości działały poprawnie, musisz zamiast tego użyć klas nowego stylu (w Pythonie 2 musisz dziedziczyć z
object
). Po prostu zadeklaruj swoją klasę jakoMyClass(object)
:To działa:
Innym szczegółem, który może powodować problemy, jest to, że obie metody wymagają tej samej nazwy, aby właściwość działała. Jeśli zdefiniujesz setera z inną nazwą, jak ta, to nie zadziała :
I jeszcze jedna rzecz, która na początku nie jest łatwa do zauważenia, to kolejność: najpierw należy zdefiniować metodę pobierającą . Jeśli najpierw zdefiniujesz ustawiającego, pojawi się
name 'x' is not defined
błąd.źródło
Tylko uwaga dla innych osób, które natkną się tutaj, szukając tego wyjątku: obie funkcje muszą mieć tę samą nazwę. Nazwanie metod w następujący sposób spowoduje wyjątek:
Zamiast tego nadaj obu metodom tę samą nazwę
Należy również zauważyć, że kolejność deklaracji ma znaczenie. Getter musi być zdefiniowany przed ustawiaczem w pliku, w przeciwnym razie otrzymasz rozszerzenie
NameError: name 'x' is not defined
źródło
NameError: name 'x' is not defined
wyjątek.Musisz użyć klas nowego stylu, które robisz, wyprowadzając swoją klasę z obiektu:
Wtedy powinno działać.
źródło
W przypadku, gdy ktoś przychodzi tutaj z Google, oprócz powyższych odpowiedzi chciałbym dodać, że wymaga to szczególnej uwagi przy wywoływaniu setera z
__init__
metody Twojej klasy opartej na tej odpowiedzi. Konkretnie:źródło
__init__
metody, ale z każdej innej metody w klasie.