MRO in succession and super-detailed

Source: Internet
Author: User

Python advanced-MRO and super in succession

Write in front

If not specifically stated, the following are based on Python3

Summary
This article describes Python how an inheritance relationship can be super() returned by calling the "parent class" method, super(Type, CurrentClass) returning the proxy for the CurrentClass MRO Type next class, and how to design the Python class for proper initialization.

1. Parent class method invocation in single inheritance

In inheritance, it is necessary to call the parent class method. There are many scenarios for calling the parent class method:

    • For example, you must call the parent class's constructor __init__ to properly initialize the parent class instance property so that the subclass instance object can inherit the instance property of the parent class instance object;

    • If you need to override the parent class method, there is sometimes no need to completely abandon the parent class implementation, just add some implementations before and after the parent class implementation, and ultimately call the parent class method

Single inheritance is the simplest inheritance relationship, multiple inheritance is too complex and error-prone to use. Therefore, some high-level languages completely abandon multiple inheritance, only support single inheritance; some high-level languages support multiple inheritance, but it is not recommended to use multiple inheritance. Pythonalso, in the inability to fully grasp the multi-inheritance, it is best not to use, single inheritance to meet most of the needs.

1.1 Non-binding method invocation

The difference between a binding method and a non-binding method see: Python Basics-Classes

There are two classes of inheritance relationships, as follows:

Class D (object):d EF test (self):p rint (' Test in D ') class C (d):d EF-Test (self):p rint (' Test-in-C ')        d.test (self)

It is now required to C invoke the implementation of the parent class in the function of the subclass test D test . The most straightforward way we can think of is to refer directly to the D function member of the class object test :

Class D (object):d EF test (self):p rint (' Test in D ') class C (d):d EF test (self):p rint (' Test in C ')

Try testing:

c = C () c.test ()

Output

Test in CTest in D

It seems that the non-binding approach does satisfy the need for the current invocation of the parent class method.

1.2 Builtin function Super

Refer to Python tutorial for a description of super:super(\[type\[, object-or-type\]\])

Return a proxy object, delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that has been overridden in a class. The search order is same as, used by GetAttr () except, the type itself is skipped.

superThe function returns type the proxy object for the parent class or sibling method call of the delegate class. superused to invoke a parent class method that has been overridden in a subclass. The search order of the method is the same as the getattr() function, except that the parameter class type itself is ignored.

1.3 Binding Method Invocation

Invoking the parent class method with a binding method naturally cannot explicitly pass in the parameter current object ( self ). Now the super function can be scoped to the proxy of the parent class, because there is only one parent class in the single-inheritance neutron class, so the parent class is explicit, and we fully understand which parent class method is called:

Class D (object):d EF test (self):p rint (' Test in D ') class C (d):d EF test (self):p rint (' Test in C ') super (). Test () # super (C, SE LF). The omitted form of test ()

2. In-depth super

In fact, the super proxy object returned by the function is one bultin class super , and as its name implies, the class super proxies the parent class of the subclass. In a single-inheritance relationship, the class of the super proxy is easy to find, that is, the only parent of the subclass, but in a multi-inheritance relationship, super there is a possibility to proxy subclasses of siblings in addition to the parent class that can proxy subclasses.

2.1 Complex Multiple inheritance

In a multi-inheritance relationship, inheritance relationships can be quite complex.

Class D (object):    def test (self):p rint (' Test in D ') class C (d):    def test (self):p rint (' Test in C ') class B (d):    def test (self):p rint (' Test in B ') class A (b, C):p

The class A inheritance hierarchy is as follows:

  Object    |    D   /\  B   C   \/    A

Athere is a diamond structure in the inheritance relationship of a class, that A is, you can reach a parent class from a class through multiple paths D .

If you now require A a method that calls the " parent class " In a class test , you need a test search-parsing order of the methods to determine exactly which method to invoke B,C或D test .

2.2 Method parsing order (MRO)

The search order of the methods proposed above test is the method parsing order.

Depth first
PythonIn legacy classes, the method parsing order is depth-first, and multiple parent classes are left-to-right.
Breadth First
PythonIn the new class, the method parsing order is breadth-first, and multiple parent classes are left-to-right.

So the above parsing order is: A -> B -> C -> D -> object .

Python, the properties of the class __mro__ show the method search order, which can be called mro() or directly referenced to __mro__ get the search order:

Print (A.MRO ()) print (a.__mro__)

Output

[<class ' __main__. A ';, <class ' __main__. B ';, <class ' __main__. C ';, <class ' __main__. D ';, <class ' object ';] (<class ' __main__. A ';, <class ' __main__. B ';, <class ' __main__. C ';, <class ' __main__. D ';, <class ' object ' >)

So

A = A () a.test () # Output:test in B

Changes in MRO
Even in the same class, the back-and-forth relationship between positions in different MRO is different. such as the following classes:

Class D (object):    def test (self):p rint (' Test in D ') class C (d):    def test (self):p rint (' Test in C ') class B (d):    def test (self):p rint (' Test in B ')

Bthe inheritance hierarchy for a class is:

  Object    |    D   /\  C   B

BMRO for class:B -> D -> object
AMRO for comparison classes:A -> B -> C -> D -> object
In the same class B , location relationships are different in two different MRO. It can be said that by adding new subclasses to existing inheritance relationships, new classes are introduced into the MRO and the parsing order is changed.

As you can imagine, the B super method that is actually called in different MRO is different in the class's Test by calling the parent class method.

As follows:

Class D (object):    def test (self):p rint (' Test in D ') class C (d):    def test (self):p rint (' Test in C ') super (). Test () Class B (D):    def test (self):p rint (' Test in B ') super (). Test () class A (b, C):p ASSB = B () b.test () print (' ========== ') a = a () A.test ()

Output

Test in Btest in D==========test in Btest in CTest in D

Because of the subclass in the original class relationship, the method called in the method B C A B test super test has changed, the original call is the method of its parent class, D test now calls its sibling class Cthe test method.
From here it can be seen super that the parent class is not always the surrogate subclass, and it is possible to proxy its sibling class.

Therefore, in the design of the multi-inheritance relationship of the class system, pay special attention to this point.

2.3 See Super Method again

Method super([type[, object-or-type]]) that returns the proxy for the type parent class or sibling class.
If the second argument is omitted, the returned super object is not bound to a certain one MRO :

    • If the second argument is an object, then it isinstance(obj, type) must be True ;

    • If the second argument is a type, then it issubclass(type2, type) must be True , that is, the second parameter type is a subclass of the first parameter type.

superwhen the second parameter of a function is present, its implementation is probably as follows:

Def super (CLS, inst):    MRO = Inst.__class__.mro () # always the most derived Classreturn Mro[mro.index (CLS) + 1]

Obviously, the super second parameter is returned in the corresponding class MRO list, the first parameter type of the next class of the proxy. Therefore, it is necessary to require that the first parameter be type present in the second parameter class MRO , only the first parameter class is the parent class of the class of the second argument, which is guaranteed.

super()
superThe function is required to have parameters and there is no function without arguments super . Called in a class definition, super() is an ellipsis, and the interpreter fills in the necessary parameters. The first parameter of the fill is the current class, and the second parameter is self :

Super () = Super (Current_class, self)

Therefore, super() this notation is destined to be used only in the class definition.

Now look at the inheritance relationship above:

Class D (object):d EF test (self):p rint (' Test in D '), Class C (d):d EF test (self):p rint (' Test in C ') # super (). Test () # is equivalent to the following notation s Uper (C, self). Test () # Returns the Agent Class B (D):d EF test (self):p rint (' Test in B ') # super (). Test () # for the MRO of the corresponding class, class C. The following notation is equivalent to super (b, self). Test () # Returns the Agent Class A (b, C) for the next class of class B in the MRO of the self-corresponding class,:p the

So:

b = B () b.test () # Based on Class B MRO (B->d->object), super () Proxy in class B dprint (' ========== ') a = A () a.test () # MRO based on Class A (a->b- >c->d->object), super () agent C in class B

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.