Super in python

Source: Internet
Author: User
Python super

I. Problem Discovery and Proposal

In the method of a Python class, to call a method of the parent class, before Python 2.2, the usual method is as follows:

Code Segment 1:

Class:
Def _ init _ (self ):
Print "enter"
Print "leave"

Class B ():
Def _ init _ (self ):
Print "enter B"
A. _ init _ (self)
Print "leave B"

>>> B = B ()

Enter B
Enter
Leave
Leave B

That is, use non-bound class methods (Methods referenced by class names), and introduce the objects to be bound (self) in the parameter list to call the parent class.

The disadvantage is that when the parent class of A subclass changes (for example, when the parent class of Class B changes from A to C), the entire class definition must be traversed, replace all the class names of non-bound methods, such as code snippet 2,

Code Segment 2:

Class B (C): # A --> C
Def _ init _ (self ):
Print "enter B"
C. _ init _ (self) # A --> C
Print "leave B"

If the code is simple, such changes may be acceptable. However, if the code volume is large, such modifications may be disastrous.

Therefore, since Python 2.2, Python has added a keyword "super" to solve this problem. The official documentation for Python 2.3 is as follows:

Super (type [, object-or-type])

Return the superclass of type. If the second argument is omitted the super object
Returned is unbound. 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. super () only works for new-style classes.

A typical use for calling a cooperative superclass method is:

Class C (B ):
Def meth (self, arg ):
Super (C, self). meth (arg)

New in version 2.2.

From the description, we can rewrite Class B as code Segment 3:

Code Segment 3:

Class A (object): # A must be new-style class
Def _ init _ (self ):
Print "enter"
Print "leave"

Class B (C): # A --> C
Def _ init _ (self ):
Print "enter B"
Super (B, self). _ init __()
Print "leave B"

Try to execute the same code above, and the results are consistent, but there is only one modified code, which minimizes the maintenance of the Code, which is a good usage. Therefore, in our development process, the super keyword is widely used and has always performed well.

In our impression, for super (B, self ). _ init _ () is as follows: super (B, self) first finds the parent class of B (Class ), then, convert the self object of Class B to the object of Class A (in some way, I have never studied what the method is ), the converted Class A object then calls its own _ init _ function. Considering that super only specifies the subclass mechanism, in the multi-inheritance class definition, we usually retain the method similar to code segment 1.

One day, a colleague designed a relatively complex class architecture (we should not care whether the class system design is reasonable, but just take this example as a question to study ), code example 4:

Code segment 4:

Class A (object ):
Def _ init _ (self ):
Print "enter"
Print "leave"

Class B (object ):
Def _ init _ (self ):
Print "enter B"
Print "leave B"

Class C ():
Def _ init _ (self ):
Print "enter C"
Super (C, self). _ init __()
Print "leave C"

Class D ():
Def _ init _ (self ):
Print "enter D"
Super (D, self). _ init __()
Print "leave D"
Class E (B, C ):
Def _ init _ (self ):
Print "enter E"
B. _ init _ (self)
C. _ init _ (self)
Print "leave E"

Class F (E, D ):
Def _ init _ (self ):
Print "enter F"
E. _ init _ (self)
D. _ init _ (self)
Print "leave F"

>>> F = F ()

Enter F
Enter E
Enter B
Leave B
Enter C
Enter D
Enter
Leave
Leave D
Leave C
Leave E
Enter D
Enter
Leave
Leave D
Leave F

Obviously, the initialization functions of Class A and Class D are repeatedly called twice, which is not the expected result! The expected result is that only the initialization function of Class A is called twice. In fact, this is A problem that must be faced by the multi-inheritance class system. We will draw out the class system of code segment 4, such:

Object
| \
|
|/|
B C D
\/|
E |
\ |
F

According to our understanding of super, we can see that when calling Class C's initialization function, we should call class A's initialization function, but actually called Class D's initialization function. A strange problem!

That is to say, mro records the sequence of class types of all base classes of a class. Check the mro records and find that there are 7 elements and the seven class names are:

F e B C D A object

This explains why super (C, self). _ init _ () is used in C. _ init _ to call the initialization function of class D. ???

We rewrite code segment 4:

Code segment 9:

Class A (object ):
Def _ init _ (self ):
Print "enter"
Super (A, self). _ init _ () # new
Print "leave"

Class B (object ):
Def _ init _ (self ):
Print "enter B"
Super (B, self). _ init _ () # new
Print "leave B"

Class C ():
Def _ init _ (self ):
Print "enter C"
Super (C, self). _ init __()
Print "leave C"

Class D ():
Def _ init _ (self ):
Print "enter D"
Super (D, self). _ init __()
Print "leave D"
Class E (B, C ):
Def _ init _ (self ):
Print "enter E"
Super (E, self). _ init _ () # change
Print "leave E"

Class F (E, D ):
Def _ init _ (self ):
Print "enter F"
Super (F, self). _ init _ () # change
Print "leave F"

>>> F = F ()

Enter F
Enter E
Enter B
Enter C
Enter D
Enter
Leave
Leave D
Leave C
Leave B
Leave E
Leave F

Obviously, the initialization of F not only completes the call of all parent classes, but also ensures that the initialization function of each parent class is called only once.

Iii. Continuation Discussion

Let's re-look at the class system diagram above. If we look at each class as a node and the direct inheritance relationship between each subclass and its parent class as a directed edge, then the system diagram will become a directed graph. It cannot be found that the mro sequence is just a topological sorting sequence of the directed graph.

In this way, we get another result: How does Python process multi-inheritance. The traditional object-oriented programming language (such as C ++) that supports multi-inheritance is a problem in which the constructor of the parent class in Multi-inheritance is called multiple times through virtual inheritance, python is processed by mro.

But this gives us a difficult problem: for the compiler who provides the class system, he does not know how the user will use his class system. That is to say, the following classes are incorrect, it may lead to errors of the original class system, and such errors are very concealed and difficult to be found.

Iv. Summary

1. super is not a function. It is a class name. For example, super (B, self) actually calls the initialization function of the super class,
Generates a super object;
2. The super class initialization function does not perform any special operations, but simply records the class type and specific instance;
3. The call of super (B, self). func is not used to call the func function of the parent class of the current class;
4. The multiple inheritance classes of Python use mro to ensure that the functions of each parent class are called one by one, and each parent class function is also guaranteed.
Only one call (if each class uses super );
5. mixing super classes and unbound functions is a dangerous action, which may cause the parent class function to be called not to be called or
Parent functions are called multiple times.

========================================================== ========================================================== ======================================

[Python mro & Python class type]

Classes in Python are classified into two categories: classical and new-style.

Classical is always used by Python, and new-style is introduced by Python 2.2.

A class inherits from the object, or any of its bases classes inherits from the object. This class is a new-style class.

[MRO-Method Resolution Order]

For the classical and new-style classes, in the complex inheritance structure, the call sequence (MRO) of the method in the class is also different.

ClassicalYesDepth first,New-styleYesBreadth First. For example:

[Sample Code]

Class D:
Def foo (self ):
Print "class D"

Class B (D ):
Pass

Class C (D ):
Def foo (self ):
Print "class C"

Class A (B, C ):
Pass

F = ()
F. foo ()

For the above classical case, the result is "class D ". If you change the code to class D (object):, the result is "class C ".

========================================================== ========================================================== ================

The Python 2.3 Method Resolution Order-the C3 Method Resolution Order

C3 linearization

From Wikipedia, the free encyclopedia

In computing,C3 superclass linearizationIs an algorithm used
Primarily to obtain the order in which methods shoshould be inherited (the "linearization"), and is
Often termed "MRO" for Method Resolution Order. The name C3 refers to the three important properties of the resulting linearization: a consistent extended precedence
Graph, preservation of local precedence order, and monotonicity.
It was first published at the 1996 OOPSLA conference, in a paper entitled "A Monotonic Superclass Linearization for Dylan ".[1] Subsequently,
It has been chosen as the default algorithm for method resolution in Python 2.3 (and newer ),[2][3] Perl
6,[4] and Parrot.[5] It
Is also available as an alternative, non-default MRO in the core of Perl 5 starting with version 5.10.0.[6]
Extension implementation for earlier versions of Perl 5 namedClass::C3Exists on CPAN.[7]

The Python 2.3 Method Resolution Order-C3

Related Article

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.