代码之家  ›  专栏  ›  技术社区  ›  Maxim Popravko

Python中具有新样式属性的“无法设置属性”

  •  64
  • Maxim Popravko  · 技术社区  · 16 年前

    我正在尝试使用新样式的属性声明:

    class C(object):
        def __init__(self):
            self._x = 0
    
        @property
        def x(self):
            print 'getting'
            return self._x
    
        @x.setter
        def set_x(self, value):
            print 'setting'
            self._x = value
    
    if __name__ == '__main__':
        c = C()
        print c.x
        c.x = 10
        print c.x
    

    并在控制台中看到以下内容:

    pydev debugger: starting
    getting
    0
    File "\test.py", line 55, in <module>
    c.x = 10
    AttributeError: can't set attribute
    

    我做错什么了? P、 美国:旧式的声明很有效。

    4 回复  |  直到 9 年前
        1
  •  97
  •   John Y    10 年前

    The documentation says the following 关于使用 property :

    请确保为其他函数指定与原始属性相同的名称(在本例中为x)

    我不知道这是为什么如果你用 财产 作为返回属性的函数,可以随意调用这些方法。

    因此,您需要将代码更改为以下内容:

    @x.setter
    def x(self, value):
        'setting'
        self._x = value
    
        2
  •  14
  •   Ignacio Vazquez-Abrams    16 年前

    setter方法必须与getter同名。别担心,装潢师知道如何区分它们。

    @x.setter
    def x(self, value):
     ...
    
        3
  •  6
  •   Kyle    15 年前

    当您调用@x.setter、@x.getter或@x.deleter时,您正在创建一个新的属性对象,并为它指定要装饰的函数的名称。所以,真正重要的是,上一次在类定义中使用@x.*er装饰符时,它有您真正想要使用的名称。但是,由于这会使您的类命名空间被希望使用的属性的不完整版本所污染,因此最好使用相同的名称来清理它们。

        4
  •  1
  •   Tcll    8 年前

    如果你不想要额外的 _x name slot,下面是一个复杂的小技巧:
    (用Py34测试)

    >>> class C(object):
        __slots__ = ['x'] # create a member_descriptor
        def __init__( self ):
            self.x = 0
            # or use this if you don't want to call x_setter:
            #set_x( self, 0 )
    
    
    >>> get_x = C.x.__get__ # member_descriptor getter
    >>> set_x = C.x.__set__ # member_descriptor setter
    >>> # define custom wrappers:
    >>> def x_getter( self ):
        print('getting')
        return get_x( self )
    
    >>> def x_setter( self, value ):
        print('setting')
        set_x( self, value )
    
    
    >>> C.x = property( x_getter, x_setter ) # replace the member_descriptor
    >>> c = C()
    setting
    >>> print(c.x)
    getting
    0
    >>> c.x = 10
    setting
    >>>