当前位置:  开发笔记 > 编程语言 > 正文

为什么Python中的@ foo.setter不适合我?

如何解决《为什么Python中的@foo.setter不适合我?》经验,为你挑选了4个好方法。

所以,我正在使用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不起作用!

我错过了什么?



1> nosklo..:

您似乎在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出现错误.


它适用于python 3,因为每个类都是一个新风格的类,不再有"经典"类.
在Python3中,不再需要 - "经典"类对于setter来说是正常的:-)

2> Andrew Hows..:

对于在这里偶然发现寻找此异常的其他人的注意事项:两个函数都需要具有相同的名称.如下命名方法将导致异常:

@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


这个答案很棒.我认为要完成,如果你能说顺序很重要,那就好了,就是说,getter必须在代码中的setter之前.否则,你会得到一个`NameError:name'x'未定义`异常.

3> MrTopf..:

您需要使用通过从对象派生类来执行的新式类:

class testDec(object):
   ....

然后它应该工作.



4> akotian..:

如果有人从谷歌来到这里,除了上面的答案,我想补充一点,__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

推荐阅读
手机用户2402851335
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有