Python built-in functions (63) -- super, python built-in 63 super
English document:
super
([Type[,Object-or-type])
Return a proxy object that delegates method callto a parent or sibling classType. This is useful for accessing inherited methods that have been overridden in a class. The search order is same as that usedgetattr()
Could t thatTypeItself is skipped.
The__mro__
Attribute ofTypeLists the method resolution search order used by bothgetattr()
Andsuper()
. The attribute is dynamic and can change whenever the inheritance hierarchy is updated.
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 (this is useful for classmethods ).
There are two typical use casesSuper. In a class hierarchy with single inheritance,SuperCan be used to refer to parent classes without naming them explicitly, thus making the code more maintainable. This use closely parallels the useSuperIn other programming languages.
The second use case is to support cooperative multiple inheritance in a dynamic execution environment. this use case is unique to Python and is not found in statically compiled ages or ages that only support single inheritance. this makes it possible to implement "diamond diagrams" where multiple base classes implement the same method. good design dictates that this method have the same calling signature in every case (because the order of CILS is determined at runtime, because that order adapts to changes in the class hierarchy, and because that order can include sibling classes that are unknown prior to runtime ).
Note thatsuper()
Is implemented as part of the binding process for explicit dotted attribute lookups suchsuper().__getitem__(name)
. It does so by implementing its own__getattribute__()
Method for searching classes in a predictable order that supports cooperative multiple inheritance. Accordingly,super()
Is undefined for implicit lookups using statements or operators suchsuper()[name]
.
Also note that, aside from the zero argument form,super()
Is not limited to use inside methods. the two argument form specifies the arguments exactly and makes the appropriate references. the zero argument form only works inside a class definition, as the compiler fills in the necessary details to correctly retrieve the class being defined, as well as accessing the current instance for ordinary methods.
Note:
1. The super function returns a proxy object through which you can call the method of the parent class or sibling class of the class without displaying the Class Name of the specified parent class or sibling class.
2. Why super?
Before the earliest, the method used to call parent class (A) In subclass (B) was as follows:
# Define parent class A >>> class A (object): def _ init _ (self): print ('a. _ init _ ') # instantiate A >>> a = A (). _ init __# define subclass B, inherit from A, and call the _ init _ method of a in the _ init _ method of B >>> class B (): def _ init _ (self): print ('B. _ init _ '). _ init _ (self) # instantiate B> B = B () B. _ init _. _ init __
If you want to change A new class (A1) and change the inheritance relationship (B-> A to B-> A1), you need to make the following changes to all classes:
# Define a new parent class A1 >>> class A1 (object): def _ init _ (self): print ('a1. _ init _ ') # change the inheritance relationship B-> A to B-> A1> class B (A1): def _ init _ (self ): print ('B. _ init _ ') A1. _ init _ (self) # Call the _ init _ method of the new parent class A1. >>> B = B () b. _ init _ A1. _ init __# assume you forgot to modify. _ init _ (self) >>> class B (A1): def _ init _ (self): print ('B. _ init _ '). _ init _ (self) # The _ init _ method of a is still called> B = B () B. _ init _. _ init __
After super is introduced, the Class Name of the specified parent class does not need to be displayed, enhancing the maintainability of the program:
# B-> A uses the super method to call the parent class method> class B (A): def _ init _ (self): print ('B. _ init _ ') super (). _ init _ () # can call the parent class method correctly> B = B () B. _ init _. _ init __# change the inheritance relationship B-> A to B-> A1. do not modify the method of calling the parent class method >>> class B (A1 ): def _ init _ (self): print ('B. _ init _ ') super (). _ init _ () # The parent class method can also be correctly called >>> B = B () B. _ init _ A1. _ init __
3. super (Class Name, self) without any parameters is equivalent to super (Class Name, self), which is used in the subclass of a single inheritance relationship.
# Super without parameter >>> class B (A1): def _ init _ (self): print ('B. _ init _ ') super (). _ init _ () # can call the parent class method correctly> B = B () B. _ init _ A1. _ init __# super has two parameters (class Name, self) >>> class B (A1): def _ init _ (self ): print ('B. _ init _ ') super (B, self ). _ init _ () # The parent class method can also be correctly called >>> B = B () B. _ init _ A1. _ init __
4. If 2nd parameters are not passed in, the proxy object is not bound with an inheritance relationship.
# Super 2nd parameters are not passed in. The generated proxy object is not bound with an inheritance relationship >>> class B (A1): def _ init _ (self): print ('B. _ init _ ') super (B ). _ init _ () # super (B ). when the _ init _ () method is executed, the parent class method is not called >>> B = B () B. _ init __
5. If 2nd parameters are an object, the object must be an instance of the type specified by 1st parameters. This type of relationship is mostly used in subclass of multi-level inheritance relationships.
# Define parent class A >>> class A (object): def _ init _ (self): print ('a. _ init _ ') # define subclass B and inherit from class A, __init _ to call the _ init _ method of the parent class >>> class B (): def _ init _ (self): print ('B. _ init _ ') super (). _ init _ () # define subclass C, inherit from class B ,__ init _ and call the _ init _ method of the parent class >>> class C (B ): def _ init _ (self): print ('C. _ init _ ') super (). _ init _ () # when instantiating C, execute the _ init _ method of C and call the _ init _ method of direct parent class B, further call the _ init _ method> c = C () C. _ init _ B. _ init _. _ init __# re-define subclass C. The inheritance relationship remains unchanged. when calling the parent class method _ init _, use super (B, self) >>> class C (B ): def _ init _ (self): print ('C. _ init _ ') super (B, self ). _ init _ () # execute the _ init _ method of c when instantiating C. The super (B, self) proxy finds the parent class A of B, to convert self to B, the _ init _ method of a is called directly, and the _ init _ method of B is skipped. >>> c = C () c. _ init _. _ init __# define a new class D >>> class D (object): def _ init _ (self): print ('d. _ init _ ') # re-define C and keep the inheritance relationship unchanged. when calling the parent class method _ init _, use super (D, self) >>> class C (B): def _ init _ (self): print ('C. _ init _ ') super (D, self ). _ init _ () # execute the _ init _ method of c when instantiating C. The super (D, self) proxy finds the parent class object of D, convert self to an instance of D. Because D and C do not have an inheritance relationship, self cannot be converted to an instance of D. Therefore, an error is returned> c = C () C. _ init _ Traceback (most recent call last): File "<pyshell #14>", line 1, in <module> c = C () file "<pyshell #13>", line 4, in _ init _ super (D, self ). _ init _ () TypeError: super (type, obj): obj must be an instance or subtype of type
6. If 2nd parameters are a type, the type must be a subclass of the type specified by 1st parameters. This type of relationship is mostly used in subclass of multi-level inheritance relationships and is applicable to Class methods.
# Define the parent class A and define A class method sayHello >>> class A (object): @ classmethod def sayHello (cls): print ('a. sayHello ') # define subclass B, inherit from class A, override class method sayHello, and call the sayHello method of the parent class >>> class B (A): @ classmethod def sayHello (cls): print ('B. sayHello ') super (). sayHello () # define subclass C, inherit B, override class method sayHello, and call the sayHello method of the parent class >>> class C (B): @ classmethod def sayHello (cls): print ('C. sayHello ') super (). sayHello () # Call the class method sayHello of C, which calls the class method sayHello of direct parent class B of C, the sayHello method of B calls the class method sayHello> C. sayHello () C. sayHelloB. sayHelloA. sayHello # re-define class C and keep the inheritance relationship unchanged. Use super (C, C) to call the parent class method >>> class C (B): @ classmethod def sayHello (cls): print ('C. sayHello ') super (C, C ). sayHello () # Call the class method sayHello of C, super (C, C) proxy object, find the direct parent class B of C, then, the class method sayHello of the direct parent class B of C is called. when calling the sayHello method of B, the class method of the direct parent class A of B is called. sayHello >>> C. sayHello () C. sayHelloB. sayHelloA. sayHello # re-define class C and keep the inheritance relationship unchanged. Use super (B, C) to call the parent class method >>> class C (B): @ classmethod def sayHello (cls): print ('C. sayHello ') super (B, C ). sayHello () # Call the class method sayHello of C, super (B, C) proxy object, find the direct parent class A of B, then, the class method sayHello of the direct parent class A of B is called, And the sayHello method of B is not called in the middle> C. sayHello () C. sayHelloA. sayHello # defines A new class D, which has no inheritance relationship with A, B, and C> class D (object): @ classmethod def sayHello (cls): print ('d. sayhello') # redefine class C and keep the inheritance relationship unchanged. Use super (D, C) to call the parent class method >>> class C (B ): @ classmethod def sayHello (cls): print ('C. sayHello ') super (D, C ). sayHello () # Call C's class methods sayHello, super (D, C) proxy object, find B's direct parent class object, and then convert C to D Class, conversion failed call error> C. sayHello () C. sayHelloTraceback (most recent call last): File "<pyshell #81>", line 1, in <module> C. sayHello () File "<pyshell #80>", line 5, in sayHello super (D, C ). sayHello () TypeError: super (type, obj): obj must be an instance or subtype of type