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