super not behaving as I expected
Peter Otten
__peter__ at web.de
Sun Mar 29 10:49:03 EDT 2020
Antoon Pardon wrote:
>
> I have the following program
>
> class slt:
> __slots__ = ()
>
> def getslots(self):
> print("### slots =", self.__slots__)
> if self.__slots__ == ():
> return []
> else:
> ls = super().getslots()
> ls.extend(self.__slots__)
> return ls
>
> def __str__(self):
> ls = []
> attrs = self.getslots()
> for attr in attrs:
> ls.append(str(getattr( self, attr)))
> return '->'.join(ls)
>
>
> class slt1 (slt):
> __slots__ = 'fld1', 'fld2'
>
> def __init__(self, vl1, vl2):
> self.fld1 = vl1
> self.fld2 = vl2
>
> class slt2(slt1):
> __slots__ = 'fld3',
>
> def __init__(self, vl1, vl2, vl3):
> self.fld1 = vl1
> self.fld2 = vl2
> self.fld3 = vl3
>
> rc1 = slt1(4, 7)
> rc2 = slt2(11, 18, 29)
>
> print(rc1)
> print(rc2)
>
> When I call this I would expect to see the following:
>
> ### slots = ('fld1', 'fld2')
> ### slots = ()
> 4->7
> ### slots = (fld3,)
> ### slots = ('fld1', 'fld2')
> ### slots = ()
> 11->18->29
>
> What I actually get is:
>
> ### slots = ('fld1', 'fld2')
> Traceback (most recent call last):
> File "slottest", line 39, in <module>
> print(rc1)
> File "slottest", line 15, in __str__
> attrs = self.getslots()
> File "slottest", line 9, in getslots
> ls = super().getslots()
> AttributeError: 'super' object has no attribute 'getslots'
>
Well...
super().method
looks up method in the parent class of the class where it's used -- in your
case the parent class of slt, or object.
self.attribute
looks up the attribute in the instance, and if that fails works its way up
the inheritance tree follong the mro; here it succeeds in slt1. This leeds
to execution of the else branch in getslots() which in turn tries to invoke
object.getslots() -- and fails.
That would be the normal behaviour. The __slots__ attribute is special, so
there may be subtle differences.
Anyway, here's my attempt to collect inherited slots:
@classmethod
def get_slots(cls):
all_slots = set()
for C in cls.__mro__:
try:
slots = C.__slots__
except AttributeError:
assert C is object
else:
all_slots.update(slots)
return all_slots
More information about the Python-list
mailing list