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()
调用?
答案 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'