In-depth analysis of the usage of the super keyword in Python Programming

Source: Internet
Author: User
The super keyword can be used when a Python subclass calls a parent class member. during initialization, pay attention to the differences between super () and _ init, next we will go into the usage of the super keyword in Python Programming: there are not many definitions about super in the official document, the general meaning is to return a proxy object so that you can call some inherited methods. The search mechanism follows the mro rules. The most common situation is shown in the following example:

class C(B):  def method(self, arg):    super(C, self).method(arg)

Subclass C overrides the method of the same name in parent class B, and calls the method of the same name in the parent class through the proxy object instantiated by super in the rewriting implementation.

The signature of the initial method of the super class is as follows:

def __init__(self, type1, type2=None): # known special case of super.__init__    """    super(type, obj) -> bound super object; requires isinstance(obj, type)    super(type) -> unbound super object    super(type, type2) -> bound super object; requires issubclass(type2, type)    Typical use to call a cooperative superclass method:

Except self, one or two parameters are accepted. as stated in the annotation declaration, when two parameters are accepted, the bound super instance is returned, when the second parameter is omitted, the unbound super object is returned.

Generally, when an inherited class or static method is called, you do not need to bind a specific instance. in this case, super (type, type2) is used ). some_method can achieve the goal. of course, super (type, obj) can also be used in this case. super objects can also be processed using custom getattribute methods. However, the latter is generally used to call the instance method, so that the corresponding instance can be passed in when the method is searched to obtain the bound instance method:

class A(object):  def __init__(self):    pass  @classmethod  def klass_meth(cls):    pass  @staticmethod  def static_meth():    pass  def test(self):    passclass B(A):  pass>>> b = B()>>> super(B, b).test
 
  >>>> super(B, b).klass_meth
  
   >>>> super(B, b).static_meth
   
    >>> super(B, B).test
    
     >>> super(B, B).klass_meth
     
      >>>> super(B,B).satic_meth>>> super(B,B).static_meth
      
     
    
   
  
 

When initializing the super object, the second parameter passed is actually the bound object. The first parameter sensory number can be roughly resolved as the starting point for marking the search, as shown in the preceding example: super (B, B ). test will be in B. the search method test is listed in _ mro _ apart from class B, because all methods are non-data descriptors, which will be converted to A in the custom getattribute of the super object. _ dict ['test']. _ get _ (B, B ).

Super is used in many places, except that the program does not have to specify the hardcode type to make the code more dynamic, there are other things that are required, such as using super in the meta class to find the new in baseclass to generate a custom type template, and using getattribute to prevent infinite loops.

For details about super, we recommend that you understand it with the python descriptor, because super implements the descriptor protocol, which is a non-data descriptor, this helps you better understand how super works.

Note the following four points:
1. during single inheritance, super () and _ init _ () functions are similar.

class Base(object):  def __init__(self):    print 'Base create'class childA(Base):  def __init__(self):    print 'creat A ',    Base.__init__(self)class childB(Base):  def __init__(self):    print 'creat B ',    super(childB, self).__init__()base = Base()a = childA()b = childB()

Output result:

Base createcreat A Base createcreat B Base create


You do not need to explicitly reference the base class when using super () inheritance.

2. super () can only be used in new classes

Change the base class to the old class, that is, do not inherit any base class

class Base():  def __init__(self):    print 'Base create'

During execution, when initializing B, an error is reported:

  super(childB, self).__init__()TypeError: must be type, not classobj

3. super is not the parent class, but the next class that inherits the sequence.

In multi-inheritance, the inheritance sequence is involved. super () is equivalent to returning the next class in the inheritance sequence, rather than the parent class. This function is similar to the following:

def super(class_name, self):  mro = self.__class__.mro()  return mro[mro.index(class_name) + 1]

Mro () is used to obtain the inheritance sequence of classes.

For example:

class Base(object):  def __init__(self):    print 'Base create'class childA(Base):  def __init__(self):    print 'enter A '    # Base.__init__(self)    super(childA, self).__init__()    print 'leave A'class childB(Base):  def __init__(self):    print 'enter B '    # Base.__init__(self)    super(childB, self).__init__()    print 'leave B'class childC(childA, childB):  passc = childC()print c.__class__.__mro__

The input result is as follows:

enter A enter B Base createleave Bleave A(
 
  , 
  
   , 
   
    , 
    
     , 
     
      )
     
    
   
  
 

Supder is not associated with the parent class, so the execution order is A-> B-> Base

The execution process is equivalent to: when childC () is initialized, super (childA, self) in the childA constructor is called first ). _ init _ (), super (childA, self) returns a childB class after childA in the inheritance sequence of the current class, and then executes childB (). _ init () __, which is executed in this order.

In multi-inheritance, if super (childA, self) in childA () is set ). _ init _ () is replaced with Base. _ init _ (self): During execution, after inheriting childA, it will directly jump to the Base class, skipping childB:

enter A Base createleave A(
 
  , 
  
   , 
   
    , 
    
     , 
     
      )
     
    
   
  
 

The super () method shows that the first parameter of super () can be the name of any class in the inheritance chain,

If it is itself, it will inherit the next class in turn;

If it is an inheritance chain, the previous classes will be infinitely recursive;

If it is the class after the inheritance chain, the class between the inheritance chain summary itself and the incoming class will be ignored;

For example, if you change super in childA () to super (childC, self). _ init _ (), the program will be infinitely recursive.

For example:

 File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__() File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__  super(childC, self).__init__()RuntimeError: maximum recursion depth exceeded while calling a Python object

4. super () can avoid repeated calls

If childA Base, childB inherits childA and Base, if childB needs to call the Base's _ init _ () method, it will lead to _ init __() executed Twice:

Class Base (object): def _ init _ (self): print 'base create' class childA (Base): def _ init _ (self ): print 'Enter a' Base. _ init _ (self) print 'leave a' class childB (childA, Base): def _ init _ (self): childA. _ init _ (self) Base. _ init _ (self) B = childB () Base's _ init _ () method is executed twice. enter A Base createleave ABase create uses super () yes to avoid repeated calls of class Base (object): def _ init _ (self): print 'base create' class childA (Base ): def _ init _ (self): print 'Enter a' super (childA, self ). _ init _ () print 'leave a' class childB (childA, Base): def _ init _ (self): super (childB, self ). _ init _ () B = childB () print B. _ class __. mro ()

enter A Base createleave A[
 
  , 
  
   , 
   
    , 
    
     ]
    
   
  
 

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.