super()
doesn't return the descriptor, it returns the result of getting the descriptor. It doesn't return functions either, it returns the bound method; functions act as descriptors too, and their .__get__()
method returns a method.
Because there is no a
defined on the instance, there is no value and the descriptor .__get__()
raises an AttributeError.
Things work if you define a
on instances of Foo
:
class Foo(object):
__slots__ = ('a',)
def __init__(self):
self.a = 'spam'
So, accessing a __slots__
descriptor without a value raises an 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
but give the instance a value, and the AttributeError
goes away:
>>> class Foo(object):
... __slots__ = ('a',)
... def __init__(self):
... self.a = 'spam'
...
>>> Foo.a.__get__(Foo(), Foo)
'spam'
Now super()
can find the result of the descriptor just fine (demonstrating with a different attribute name to not clobber self.a
):
>>> class Bar(Foo):
... __slots__ = ('b',)
... @property
... def b(self):
... return super(Bar, self).a
...
>>> Bar().a
'spam'