I d like to know the type of an instance obtained from super() function. I tried print(super()) and __print(type(super()))__
class Base:
def __init__(self):
pass
class Derive(Base):
def __init__(self):
print(super())
print(type(super()))
super().__init__()
d = Derive()
The result is
<super: <class Derive >, <Derive object>>
<class super >
With those result, I was wondering how super().__init__() calls the correct constructor.
From your comments, you want to know how super knows which method to call next. Super inspects the mro of the instance, knows the current class method it s in, and calls the next one in line. The following demo will work in Python 2 and 3, and in Python 2, it prints the name of each class thanks to the metaclass, so I ll use that output:
First the imports and setup to make the printing nicer:
import inspect
class Meta(type):
def __repr__(cls):
return cls.__name__
Next, we define a function to tell us what s going on based on the super object itself
def next_in_line(supobj):
print( The instance class: {} .format(supobj.__self_class__))
print( in this class s method: {} .format(supobj.__thisclass__))
mro = inspect.getmro(supobj.__self_class__)
nextindex = mro.index(supobj.__thisclass__) + 1
print( super will go to {} next .format(mro[nextindex]))
https://en.wikipedia.org/wiki/C3_linearization
https://en.wikipedia.org/wiki/C3_linearization
class O(object):
__metaclass__ = Meta
def __init__(self):
next_in_line(super(O, self))
super(O, self).__init__()
class A(O):
def __init__(self):
next_in_line(super(A, self))
super(A, self).__init__()
class B(O):
def __init__(self):
next_in_line(super(B, self))
super(B, self).__init__()
class C(O):
def __init__(self):
next_in_line(super(C, self))
super(C, self).__init__()
class D(O):
def __init__(self):
next_in_line(super(D, self))
super(D, self).__init__()
class E(O):
def __init__(self):
next_in_line(super(E, self))
super(E, self).__init__()
class K1(A, B, C):
def __init__(self):
next_in_line(super(K1, self))
super(K1, self).__init__()
class K2(D, B, E):
def __init__(self):
next_in_line(super(K2, self))
super(K2, self).__init__()
class K3(D, A):
def __init__(self):
next_in_line(super(K3, self))
super(K3, self).__init__()
class Z(K1, K2, K3):
def __init__(self):
next_in_line(super(Z, self))
super(Z, self).__init__()
Now when we print the mro of Z, we get the method resolution order defined by this algorithm applied to the inheritance tree:
>>> print(inspect.getmro(Z))
(Z, K1, K2, K3, D, A, B, C, E, O, <type object >)
And when we call Z(), because our function uses the mro, we ll visit each method in order:
>>> Z()
The instance class: Z
in this class s method: Z
super will go to K1 next
The instance class: Z
in this class s method: K1
super will go to K2 next
The instance class: Z
in this class s method: K2
super will go to K3 next
The instance class: Z
in this class s method: K3
super will go to D next
The instance class: Z
in this class s method: D
super will go to A next
The instance class: Z
in this class s method: A
super will go to B next
The instance class: Z
in this class s method: B
super will go to C next
The instance class: Z
in this class s method: C
super will go to E next
The instance class: Z
in this class s method: E
super will go to O next
The instance class: Z
in this class s method: O
super will go to <type object > next
And we stop at object.__init__. From the above we can see that super always knows what class of the instance it is in, the class s method that it is currently in, and can deduce from the instance class s MRO where to go next.
I d like to know the name of the base class?
If you only want the direct base (or more than one, in the case of multiple inheritance), you can use the __bases__ attribute, which returns a tuple
>>> Derive.__bases__
(<class __main__.Base at 0xffeb517c>,)
>>> Derive.__bases__[0].__name__
Base
I recommend the inspect module for getting the Method Resolution Order (which super follows based on the original caller s class):
>>> import inspect
>>> inspect.getmro(Derive)
(<class __main__.Derive at 0xffeb51dc>, <class __main__.Base at 0xffeb517c>)
Getting it from super
super().__self_class__ gives the instance class, and super().__thisclass__ gives us the current class. We can use the instance s MRO and look up the class that comes next. I presume you wouldn t do this in the final parent, so I m not catching an index error:
class Base:
def __init__(self):
print(super().__self_class__)
print(super().__thisclass__)
class Derive(Base):
def __init__(self):
print(super().__self_class__)
print(super().__thisclass__)
mro = inspect.getmro(super().__self_class__)
nextindex = mro.index(super().__thisclass__) + 1
print( super will go to {} next .format(mro[nextindex]))
super().__init__()
>>> d = Derive()
<class __main__.Derive >
<class __main__.Derive >
super will go to <class __main__.Base > next
<class __main__.Derive >
<class __main__.Base >
http://stackoverflow.com/questions/32014260/how-do-i-get-the-instance-methods-next-in-line-parent-class-from-super-in-p