所以,我正在使用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上调用这些函数.所以,我解雇了IDLE并检查了它:
>>> from testDec import testDec from testDec import testDec >>> t = testDec() t = testDec() >>> t.x t.x called getter Traceback (most recent call last): File "", line 1, in 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,并且没有默认值,并且它失败了.好的,好的,我理解.然而,对assign的调用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 "", line 1, in 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 >>>
可能导致问题的另一个细节是两个方法都需要相同的名称才能使属性起作用.如果您使用不同的名称定义setter,它将无法工作:
@x.setter def x_setter(self, value): ...
还有一件事情,一开始并不容易发现,是顺序:必须首先定义吸气剂.如果先定义setter,则会 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
同样重要的是要注意声明的顺序很重要.必须在文件中的setter之前定义getter,否则你将得到一个NameError: name 'x' is not defined
您需要使用通过从对象派生类来执行的新式类:
class testDec(object): ....
然后它应该工作.
如果有人从谷歌来到这里,除了上面的答案,我想补充一点,__init__
根据你的答案从你的类的方法调用setter时需要特别注意
具体:
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