Почему @foo.сеттер в Python не работает для меня?
Итак, я играю с декораторами в 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 и 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
ясно, что первый вызов работает так, как ожидалось, так как я вызываю геттер, и нет значения по умолчанию, и он терпит неудачу. Хорошо, я понимаю. Тем не менее, вызов для назначения t.x = 5 кажется, чтобы создать новое свойство x и теперь геттер не работает!
что я упустил?
4 ответов:
Вы, кажется, используете классические классы старого стиля в 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): ...и еще одна вещь, которую не совсем легко обнаружить на первый взгляд, это порядок: геттер должен быть определен первый. Если вы сначала определяете сеттер, вы получаете
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важно также отметить, что порядок декларирования вопросам. Геттер должен быть определен перед сеттером в файле, иначе вы получите
NameError: name 'x' is not defined
вам нужно использовать классы нового стиля, которые вы делаете, производя свой класс от объекта:
class testDec(object): ....тогда это должно работать.
в случае, если кто-то приходит сюда из google, в дополнение к приведенным выше ответам я хотел бы добавить, что это требует тщательного внимания при вызове сеттера из
__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
Comments