In [307]:
def who(obj):
    print(id(obj), obj)
class A:
    def m(self):
        print("A's m()")
class AA:
    pass
class B(A):
    def __init__(self):
        who(super())
        who(super(self.__class__, self))
        who(super(B))
        who(super(B, self))
        who(super(A, B))
        
class C(A):
    def __init__(self):
        print(super())
        print(super(B))
        print(super(A, C))
class D(B, C):
    def __init__(self):
        print(super().__mro__)
        print(super(D).mro())
        print(super(A, B, D).mro())

In [312]:
b = B()
dir(super(b).m())
# who(super(A))
# who(super(B))


4460835848 <super: <class 'B'>, <B object>>
4460835848 <super: <class 'B'>, <B object>>
4460835848 <super: <class 'B'>, NULL>
4460835848 <super: <class 'B'>, <B object>>
4460835848 <super: <class 'A'>, <B object>>
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-312-15d04bac6017> in <module>()
      1 b = B()
----> 2 dir(super(b).m())
      3 # who(super(A))
      4 # who(super(B))

TypeError: must be type, not B

In [295]:
class E:
    def __init__(self):
        pass
    def run(self):
        print("run")

In [296]:
e = E()
e.run()
E.run(e)


run
run

In [297]:
D.__mro__


Out[297]:
(__main__.D, __main__.B, __main__.C, __main__.A, object)

In [298]:
print(super.__doc__)


super() -> same as super(__class__, <first argument>)
super(type) -> unbound super object
super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type, type2) -> bound super object; requires issubclass(type2, type)
Typical use to call a cooperative superclass method:
class C(B):
    def meth(self, arg):
        super().meth(arg)
This works for class methods too:
class C(B):
    @classmethod
    def cmeth(cls, arg):
        super().cmeth(arg)


In [299]:
type(super)


Out[299]:
type

In [327]:
class A:
    def method(self):
        who(self)
        print("A.method")
class B(A):
    def method(self):
        who(self)
        print("B.method")
class C(B):
    __mro__ = ()
    def mro():
        return []
class D(C):
    def __init__(self):
        super(D, self).method()
        super(B, self).method()
    def mro():
        return []
        
#         who(super(C, self).method)
#         who(super(C, D).method)
#         who(super(B, D).method)

In [328]:
d = D()
d.method()
C.__mro__


4462125464 <__main__.D object at 0x109f6a198>
B.method
4462125464 <__main__.D object at 0x109f6a198>
A.method
4462125464 <__main__.D object at 0x109f6a198>
B.method
Out[328]:
(__main__.C, __main__.B, __main__.A, object)

In [306]:
super(A)


Out[306]:
<super: __main__.A, None>

In [303]:
class X:
    pass
class Y:
    def __init__(self):
        pass
who(X)
who(Y)
who(Y())


140632463716184 <class 'type'>
140632463708392 <class 'type'>
4461129344 <class '__main__.Y'>

In [372]:
class M(type):
    def __new__(metacls, cls, bases, classdict):
        return super().__new__(metacls, cls, bases, classdict)
    def mro(cls):
        return [object]

In [373]:
class N(metaclass=M):
    def method(self):
        print("N's method")
class O(N):
    def method(self):
        print("O's method")

In [374]:
O.mro()


Out[374]:
[object]

In [377]:
o = O()
O.__name__


Out[377]:
'O'

In [ ]: