Python:__slots__及其描述符的用法

时间:2013-01-09 21:14:54

标签: python python-2.7 cpython python-3.2 slots

class Foo(object):
    __slots__ = ('a',)

class Bar(Foo):
    @property
    def a(self):
        return super(Bar, self).a

 super(Bar, Bar()).a = 4

如果我使用此代码,则不起作用:

>>> super(Bar, Bar()).a = 4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'super' object has no attribute 'a'

为什么?

根据python docs__slots__已实施:

  通过为每个变量名创建描述符(实现描述符),在类级别实现

__slots__。结果,上课   属性不能用于设置实例变量的默认值   由__slots__定义;否则,class属性将覆盖   描述符赋值。

但描述符可以处理继承(至少如果用纯python编写)。

有没有人知道,为什么这不适用于__slots__

编辑:如果您正在尝试编写(虽然读取工作),似乎描述符通常不能与super()一起使用。所以我的问题是:为什么描述符是只读的,如果用super()调用?

1 个答案:

答案 0 :(得分:4)

super()不返回描述符,它返回获取描述符的结果。它也不返回函数,它返回绑定方法;函数也充当描述符,它们的.__get__()方法返回一个方法。

因为实例上没有定义a,所以没有值,描述符.__get__()引发了AttributeError。

如果您在a

的实例上定义Foo,情况就会奏效
class Foo(object):
    __slots__ = ('a',)
    def __init__(self):
        self.a = 'spam'

因此,访问没有值的__slots__描述符会引发AttributeError

>>> class Foo(object):
...     __slots__ = ('a',)
... 
>>> Foo.a
<member 'a' of 'Foo' objects>
>>> Foo().a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: a
>>> Foo.a.__get__(Foo(), Foo)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: a

但是为实例赋值,而AttributeError消失了:

>>> class Foo(object):
...     __slots__ = ('a',)
...     def __init__(self):
...         self.a = 'spam'
... 
>>> Foo.a.__get__(Foo(), Foo)
'spam'

现在super()可以很好地找到描述符的结果(使用不同的属性名称进行演示而不是clobber self.a):

>>> class Bar(Foo):
...     __slots__ = ('b',)
...     @property
...     def b(self):
...         return super(Bar, self).a
... 
>>> Bar().a
'spam'