Python multiple inheritance and super ()

I am trying to understand how multiple inheritance (i.e. C3 algorithm for method resolution order ) works in Python. An example of a toy with a classic addiction below gives me results that are against my intuition.

In particular, I noticed the following:

  • When run as-is (i.e. how Aand AAhave supercalls Base, then conclude <B> <A> <AA> <Base> </Base> </AA> </A> </B>.
  • If only the line with the inscription is (1)commented out (i.e. there is no constructor call Basein A), then the output will be <B> <A> </A> </B>.
  • If only the line with the inscription is (2)commented out (i.e. there is no constructor call Basein AA), then the output will be <B> <A> <AA> </AA> </A> </B>.
  • If both lines with the inscription (1)and are (2)commented out, then the output will be <B> <A> </A> </B>.

My questions:

  • In case 1, it seems that execution is interrupted in the constructor Abefore the constructor is Basecalled explicitly , jumps to the ("recurses into") constructor AA(as if to AAbe deduced from A), then goes down to Baseand then comes back. Is that what is happening? (I understand that MRO B->A->AA->Basecomes from C3's requirement that child classes be called before parent classes.)
  • In case 2, why the constructor was AAnever called, although in case 3 it is called?
  • 2 3, Base , AA (case 2)/A (case 3)? ( 1 , .)

MROs :

  • B: (<class '__main__.B'>, <class '__main__.A'>, <class '__main__.AA'>, <class '__main__.Base'>, <type 'object'>)
  • A: (<class '__main__.A'>, <class '__main__.Base'>, <type 'object'>)
  • AA: (<class '__main__.AA'>, <class '__main__.Base'>, <type 'object'>)
  • Base: (<class '__main__.Base'>, <type 'object'>)

:

#!/usr/bin/env python
# Using Python 2.7

class Base(object):
    def __init__(self):
        print '<Base>',
        super(Base, self).__init__()
        print '</Base>',

class A(Base):
    def __init__(self):
        print '<A>',
        super(A, self).__init__()             # (1)
        print '</A>',

class AA(Base):
    def __init__(self):
        print '<AA>',
        super(AA, self).__init__()            # (2)
        print '</AA>',

class B(A, AA):
    def __init__(self):
        print '<B>',
        super(B, self).__init__()
        print '</B>',

if __name__ == '__main__':
    obj = B()
+4
3

super "" . , super , MRO . , , .

, A AA, . , , A, AA:

  • ( MRO): B, A, AA, Base
  • 1 ( A): B, A
  • 2 ( AA); B, A, AA

, , .

super, " !" PyCon, ( !).

( ):

super Python? . , , , , .

- , "". ? , , , Python.

[...] ? . [...] , super, - . Pythons - . , . super, ? , .

+1

, :

Python C3. : , , , ( [8]). , : D, B, C, A

, (.. B) A AA.

0

MRO B, A, AA, Base. , super(A, self), self B, AA. A, super Base.

, , .

A super(A,self).__init__() Base.__init__(self), B AA.__init__(self)

, :

No, you cannot find a class allowed by super for the simple reason that different attributes can be allowed for different classes.

For example, in the code, enter a class AAmethod foo. Now:

b = B()
super(B,b).__init__() # calls A.__init__
super(B,b).foo() # calls AA.foo

The function superdoes not just find the next class in the MRO chain, it finds the next class that has the desired attribute. This is why it should return a proxy object, and not just return a class.

0
source

Source: https://habr.com/ru/post/1617029/


All Articles