How to use super function

Super in Python

1. Preface (all content is based on the code from the beginning)

class A:
    def __init__(self):
        print('A')
class B(A):
    def __init__(self):
        print('B')

if __main__ == '__main__':
    b = B() 
    # B

But in some cases, we want to be able to directly call the method of its parent class at runtime, how to do it?

class A:
    def __init__(self):
        print('A')
        
class B(A):
    def __init__(self):
    	super(B,self).__init__() 
    	# super().__init__()
    	print('B')

if __main__ == '__main__':
    b = B() 
    # B 
    # A

In python2is super(B,self).__init__(); in python3is simplified to super().__init__().

2. Since the constructor of object B can be rewritten, why call super?

Take multithreading as an example. We define our own thread class MyThreadand then inherit the Threadclass.

from  threading import Thread
class MyThread(Thread):
    def __init(self,name,user):
        self.user = user
        # self.name = name (不需要)
        super().__init__(name=name)
        

In the custom MyThreadclass, first define an initialization function, assuming that two parameters name(thread name) and user(executing user) are passed to it . Can not be used at this time self.name = name.

Because Threadthe __init__method has been implemented in the class in the source code, there are many parameters in the method, among which there are nameparameters, and a lot of logic is also implemented in the method.

In fact, let the custom MyThreadclass directly call the parent class Thread, which is equivalent to handing over the constructor to the parent class to instantiate, so that the code (method, logic) in the parent class can be reused, so in some cases, the superfunction Still need to call.

  • ThreadThe __init__part of the class source code (no need to look closely, just pay attention to the structure)
class Thread:
    """A class that represents a thread of control.

    This class can be safely subclassed in a limited fashion. There are two ways
    to specify the activity: by passing a callable object to the constructor, or
    by overriding the run() method in a subclass.

    """
    
    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, *, daemon=None):
        """This constructor should always be called with keyword arguments. Arguments are:

        *group* should be None; reserved for future extension when a ThreadGroup
        class is implemented.

        *target* is the callable object to be invoked by the run()
        method. Defaults to None, meaning nothing is called.

        *name* is the thread name. By default, a unique name is constructed of
        the form "Thread-N" where N is a small decimal number.

        *args* is the argument tuple for the target invocation. Defaults to ().

        *kwargs* is a dictionary of keyword arguments for the target
        invocation. Defaults to {}.

        If a subclass overrides the constructor, it must make sure to invoke
        the base class constructor (Thread.__init__()) before doing anything
        else to the thread.

        """
        assert group is None, "group argument must be None for now"
        if kwargs is None:
            kwargs = {
    
    }
        self._target = target
        self._name = str(name or _newname())
        self._args = args
        self._kwargs = kwargs
        if daemon is not None:
            self._daemonic = daemon
        else:
            self._daemonic = current_thread().daemon
        self._ident = None
        self._tstate_lock = None
        self._started = Event()
        self._is_stopped = False
        self._initialized = True
        # sys.stderr is not stored in the class like
        # sys.exc_info since it can be changed between instances
        self._stderr = _sys.stderr
        # For debugging and _after_fork()
        _dangling.add(self)    

3. What is the execution order of the super function?

The super function calls the constructor (method) of the parent class. This sentence is actually not completely correct. (This involves MROalgorithms)

To give a simple example, define 4 classes, B and C both inherit A, and D inherit B and C. If a superfunction is used in class D , and the parent class of class D has two (B and C), because B is before C, the constructor in B is called first.

And there are superfunctions in B, so should I print A? It can be seen from the running results that the answer is yesNO .

superThe function is not only calling the parent class function, but also in the order of the MROalgorithm inheritance chain.

class A:
    def __init__(self):
        print('A')
class B(A):
    def __init__(self):
        print('B')
        super().__init__() 
      
class C(A):
    def __init__(self):
        print('C')
        super().__init__() 
      
class D(B,C):
    def __init__(self):
        print('D')   
        super(D,self).__init__() 
            

if __main__ == '__main__':
    d = D() 
    #	D 
    #	B	
    #	A	
    #	C	

Use __mro__to see the order in the inheritance chain-first D, then B, then C, then A.

print(D.__mro__)
# (<class ‘__main__.D’>,<class ‘__main__.B’>,<class ‘__main__.C’>,<class ‘__main__.A’>,<class ‘object’>)

Guess you like

Origin blog.csdn.net/weixin_43901214/article/details/106908672