I've read the documentation for super()
multiple times but I still don't get what the two argument version returns.
Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class.
If the second argument is an object,
isinstance(obj, type)
must be true. If the second argument is a type,issubclass(type2, type)
must be true (this is useful for classmethods).
super(a,b)
mean? In context of __new__
,
Typical implementations create a new instance of the class by invoking the superclass’s __new__() method using
super(currentclass, cls).__new__(cls[, ...])
with appropriate arguments and then modifying the newly-created instance as necessary before returning it.
super(currentclass, cls).__new__(cls[, ...])
If currentclass
is equal to cls
, you have super(currentclass, currentclass)
cls
so that __init__
will be called on the returned object?The answer to "what does super
return" isn't anything like "it returns a list" or "it returns a modified copy of the second object". super
returns an object of type super
, a type designed specifically to have the qualities the documentation says it has.
Perhaps it would help to show a pure-Python implementation of super
. If super
wasn't written in C, it would look basically like this:
class super(object):
def __init__(self, klass, object_or_klass):
# The real super can be called with 0 arguments on Python 3,
# but digging into the magic that makes that work isn't relevant here.
if isinstance(object_or_klass, klass):
mro = type(object_or_klass).__mro__
self.obj_type = type(object_or_klass)
self.obj = object_or_klass
elif issubclass(object_or_klass, klass):
mro = object_or_klass.__mro__
self.obj_type = object_or_klass
self.obj = None
else:
raise TypeError
# Set up a copy of the MRO to search,
# with everything up to and including klass skipped
self.searchlist = mro[mro.index(klass)+1:]
def __getattribute__(self, name):
# self.searchlist would be infinite recursion, as would super().__getattribute__
searchlist = object.__getattribute__(self, 'searchlist')
# Search the method resolution order for the attribute we want.
for klass in searchlist:
if name in klass.__dict__:
attr = klass.__dict__[name]
break
else:
raise AttributeError
if hasattr(attr, '__get__'):
# Handle descriptors.
obj = object.__getattribute__(self, 'obj')
obj_type = object.__getattribute__(self, 'obj_type')
attr = attr.__get__(obj, obj_type)
return attr
Now you can see that super(a, b)
constructs a super
object, and super(a, b).whatever
calls the __getattribute__
method of that super
object to search the method resolution order of the second argument for the attribute we want. The attribute lookup procedure for b.whatever
is very similar, just without chopping off the first part of the MRO, and checking the instance dict if b
isn't a class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With