super () method using the super () method using

super () method using

 

We often use the super class inheritance among (), to call methods in the parent class. Such as the following:

class A:
    def func(self):
        print('OldBoy')


class B(A):
    def func(self):
        super().func()
        print('LuffyCity')


A().func()
B().func()

The resulting output is:

OldBoy
OldBoy
LuffyCity

A instantiated objects called func method, printout of  Oldboy ;

B instantiated object calls its own func method, a first call parent class printout of  Oldboy  , then print output  LuffyCity  .

This is Python3 wording, today we only discuss Python3 in super.

If the super is not used, then the same output want cut a further class B can be written:

class B(A):
    def func(self):
        A.func(self)
        print('LuffyCity')

This can achieve the same effect, but pass a self argument. Why then should use super () do?

Then I look at the class has such an inheritance relationship (diamond inheritance):

      Base
      /  \
     /    \
    A      B
     \    /
      \  /
       C

The code is as follows:

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


class A(Base):
    def __init__(self):
        Base.__init__(self)
        print('A.__init__')


class B(Base):
    def __init__(self):
        Base.__init__(self)
        print('B.__init__')


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


C()

The resulting output is:

Base.__init__
A.__init__
Base.__init__
B.__init__
C.__init__

Each subclass call the __init__ method of the parent class, want all the initialization operations are doing it again, but there is a problem, the Base class __init__ method is called twice, which is a redundant operation, it is not reasonable.

Then we rewrite to use super () the wording:

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


class A(Base):
    def __init__(self):
        super().__init__()
        print('A.__init__')


class B(Base):
    def __init__(self):
        super().__init__()
        print('B.__init__')


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


C()

The resulting output is:

Base.__init__
B.__init__
A.__init__
C.__init__ 

Such result of the execution is more satisfied, is what most people want. Why would such a result?

That is because each of us to define a class of time, Python will create a list of MRO, the order of succession to the management class.

print(C.mro())
# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]

Python through this list from left to right, for an inherited information. Python3 The classes are new classes have this property mro, you can see it is to look for breadth-first principle. Classic no mro property, but its look is depth-first principle.

Then I come back to the question of super, super let us take a look at the official definition .

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

Return a proxy object that delegates the call to a parent or sibling class class method. This is useful for accessing inherited methods class has been rewritten. Search order and getattr () using the same search order, but the type itself is skipped.

__mro__ attribute class lists getattr () and super () method of analysis using the search order. Property is dynamic and can be changed in the inheritance hierarchy update.

See the official explanation can clearly understand, super is a class that is obtained after instantiating a proxy object, rather than get a parent class, and we use the proxy object to call a method of parent or sibling classes .

Then we look at the use of super:

super() -> same as super(__class__, <first argument>)
super(type) -> unbound super object
super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type, type2) -> bound super object; requires issubclass(type2, type)

super requires at least one parameter, and the type needs to be based.

It does not pass parameter error. Only pass a parameter, then the object is not a binding, non-binding, then there is no use.

print(super(C))
print(super())

Output:

RuntimeError: super(): no arguments
<super: <class 'C'>, NULL>

In the class definition of parameters which can not write, Python will automatically pass two parameters to the super according to the situation.

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


C()

Output:

<super: <class 'C'>, <C object>>
Base.__init__
B.__init__
A.__init__
C.__init__

So we use the super in the class time parameters can be omitted.

The second use,  super (of the type, obj)  passing a class and an object, the resulting object is super bound. It also requires obj is the type of instance, may not be a direct example, is an instance of a subclass is required.

a = A()
print(super(A, a))
print(super(Base, a))

Output:

Base.__init__
A.__init__
<super: <class 'A'>, <A object>>
<super: <class 'Base'>, <A object>>

Third use,  Super (type, Type2) transmitting two classes, super object is also obtained by a binding. This requires type2 is a subclass of type.

print(super(Base, A))
print(super(Base, B))
print(super(Base, C))

 Output:

<super: <class 'Base'>, <A object>>
<super: <class 'Base'>, <B object>>
<super: <class 'Base'>, <C object>>

Next we talk about the search order in respect of the two parameters, in accordance with the parameters to calculate the MRO it?

We will fill in the parameters of super class C, and instantiate see the results output.

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

 Output:

Base.__init__
B.__init__
A.__init__
C.__init__

Look at the results and outcomes before super Motian parameters are the same.

Then we will be the first argument super changed to A:

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

Output:

Base.__init__
B.__init__
C.__init__

what! ? A .__ init__ how that get lost it? B .__ init__ more out of it?

This is a Python should be in accordance with the second argument to calculate the MRO, the argument is self, that is, C of MRO. A skip parameter (A) in order to find the back of a class (B), the implementation of his method.

Knowing this, the result output can be understood. super (A, self) .__ init __ ()  method does not perform the Base, but performs a process of B.


That we are going to talk about  super (type, obj)   and  super (type, type2) different.

code show as below:

class Base:
    def func(self):
        return 'from Base'


class A(Base):
    def func(self):
        return 'from A'


class B(Base):
    def func(self):
        return 'from B'


class C(A, B):
    def func(self):
        return 'from C'


c_obj = C()

print(super(C, C))
print(super(C, c_obj))

Output:

<super: <class 'C'>, <C object>>
<super: <class 'C'>, <C object>>

Print exactly the same result twice, verygood. That their approach is the same whether it? have a test.

print(super(C, C).func is super(C, c_obj).func)
print(super(C, C).func == super(C, c_obj).func)

Output:

false 
false

They point to the same method is neither a value not equal. Is not it a mistake? Try again look at the following.

c1 = super(C, C)
c2 = super(C, C)
print(c1 is c2)
print(c1 == c2)
print(c1.func is c2.func)
print(c1.func == c2.func)

Output:

False
False
True
True

 c1 and c2 is not an object, but their approach is the same.

That  super (C, C) .func  and  super (C, c_obj) .func  indeed different. Then print out and see what's the difference:

print(super(C, C).func)
print(super(C, c_obj).func)

 Output:

<function A.func at 0x0000000009F4D6A8>
<bound method A.func of <__main__.C object at 0x00000000022A94E0>>

 passing super second parameter is the class, a function is obtained.

 a super second argument is the object, is obtained binding method.

 The difference between function and binding methods will not repeat them here want the same results, just give function to pass a parameter, and the binding method you do not need to pass additional parameters of.

print(super(C, C).func(c_obj))
print(super(C, c_obj).func())

 Output:

from A
from A

I now summarize:

  1. super () when in use need to pass two parameters can be omitted in the class, we use the super () method of the parent class or a sibling class come;
  2. super () is calculated according to the MRO second parameter, the first search method according to a sequence parameter class.
  3. super () the second parameter is based, is a function obtained by the method, parameters used to pass self. The second parameter is the object, is obtained binding method, does not require re-transmission of the self parameter.

Some suggestions to use super () is:

  1. The method of super () call to exist;
  2. When the transmission parameters, and to make use of * args ** kwargs;
  3. The parent class of some of the features, such as [], rewritten __getattr __, super objects can not be used.
  4. super () The second parameter passed is class, class methods and static methods recommended that the parent class is called.
 
 
 

We often use the super class inheritance among (), to call methods in the parent class. Such as the following:

class A:
    def func(self):
        print('OldBoy')


class B(A):
    def func(self):
        super().func()
        print('LuffyCity')


A().func()
B().func()

The resulting output is:

OldBoy
OldBoy
LuffyCity

A instantiated objects called func method, printout of  Oldboy ;

B instantiated object calls its own func method, a first call parent class printout of  Oldboy  , then print output  LuffyCity  .

This is Python3 wording, today we only discuss Python3 in super.

If the super is not used, then the same output want cut a further class B can be written:

class B(A):
    def func(self):
        A.func(self)
        print('LuffyCity')

This can achieve the same effect, but pass a self argument. Why then should use super () do?

Then I look at the class has such an inheritance relationship (diamond inheritance):

      Base
      /  \
     /    \
    A      B
     \    /
      \  /
       C

The code is as follows:

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


class A(Base):
    def __init__(self):
        Base.__init__(self)
        print('A.__init__')


class B(Base):
    def __init__(self):
        Base.__init__(self)
        print('B.__init__')


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


C()

The resulting output is:

Base.__init__
A.__init__
Base.__init__
B.__init__
C.__init__

Each subclass call the __init__ method of the parent class, want all the initialization operations are doing it again, but there is a problem, the Base class __init__ method is called twice, which is a redundant operation, it is not reasonable.

Then we rewrite to use super () the wording:

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


class A(Base):
    def __init__(self):
        super().__init__()
        print('A.__init__')


class B(Base):
    def __init__(self):
        super().__init__()
        print('B.__init__')


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


C()

The resulting output is:

Base.__init__
B.__init__
A.__init__
C.__init__ 

Such result of the execution is more satisfied, is what most people want. Why would such a result?

That is because each of us to define a class of time, Python will create a list of MRO, the order of succession to the management class.

print(C.mro())
# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]

Python through this list from left to right, for an inherited information. Python3 The classes are new classes have this property mro, you can see it is to look for breadth-first principle. Classic no mro property, but its look is depth-first principle.

Then I come back to the question of super, super let us take a look at the official definition .

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

Return a proxy object that delegates the call to a parent or sibling class class method. This is useful for accessing inherited methods class has been rewritten. Search order and getattr () using the same search order, but the type itself is skipped.

__mro__ attribute class lists getattr () and super () method of analysis using the search order. Property is dynamic and can be changed in the inheritance hierarchy update.

See the official explanation can clearly understand, super is a class that is obtained after instantiating a proxy object, rather than get a parent class, and we use the proxy object to call a method of parent or sibling classes .

Then we look at the use of super:

super() -> same as super(__class__, <first argument>)
super(type) -> unbound super object
super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type, type2) -> bound super object; requires issubclass(type2, type)

super requires at least one parameter, and the type needs to be based.

It does not pass parameter error. Only pass a parameter, then the object is not a binding, non-binding, then there is no use.

print(super(C))
print(super())

Output:

RuntimeError: super(): no arguments
<super: <class 'C'>, NULL>

In the class definition of parameters which can not write, Python will automatically pass two parameters to the super according to the situation.

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


C()

Output:

<super: <class 'C'>, <C object>>
Base.__init__
B.__init__
A.__init__
C.__init__

So we use the super in the class time parameters can be omitted.

The second use,  super (of the type, obj)  passing a class and an object, the resulting object is super bound. It also requires obj is the type of instance, may not be a direct example, is an instance of a subclass is required.

a = A()
print(super(A, a))
print(super(Base, a))

Output:

Base.__init__
A.__init__
<super: <class 'A'>, <A object>>
<super: <class 'Base'>, <A object>>

Third use,  Super (type, Type2) transmitting two classes, super object is also obtained by a binding. This requires type2 is a subclass of type.

print(super(Base, A))
print(super(Base, B))
print(super(Base, C))

 Output:

<super: <class 'Base'>, <A object>>
<super: <class 'Base'>, <B object>>
<super: <class 'Base'>, <C object>>

Next we talk about the search order in respect of the two parameters, in accordance with the parameters to calculate the MRO it?

We will fill in the parameters of super class C, and instantiate see the results output.

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

 Output:

Base.__init__
B.__init__
A.__init__
C.__init__

Look at the results and outcomes before super Motian parameters are the same.

Then we will be the first argument super changed to A:

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

Output:

Base.__init__
B.__init__
C.__init__

what! ? A .__ init__ how that get lost it? B .__ init__ more out of it?

This is a Python should be in accordance with the second argument to calculate the MRO, the argument is self, that is, C of MRO. A skip parameter (A) in order to find the back of a class (B), the implementation of his method.

Knowing this, the result output can be understood. super (A, self) .__ init __ ()  method does not perform the Base, but performs a process of B.


That we are going to talk about  super (type, obj)   and  super (type, type2) different.

code show as below:

class Base:
    def func(self):
        return 'from Base'


class A(Base):
    def func(self):
        return 'from A'


class B(Base):
    def func(self):
        return 'from B'


class C(A, B):
    def func(self):
        return 'from C'


c_obj = C()

print(super(C, C))
print(super(C, c_obj))

Output:

<super: <class 'C'>, <C object>>
<super: <class 'C'>, <C object>>

Print exactly the same result twice, verygood. That their approach is the same whether it? have a test.

print(super(C, C).func is super(C, c_obj).func)
print(super(C, C).func == super(C, c_obj).func)

Output:

false 
false

They point to the same method is neither a value not equal. Is not it a mistake? Try again look at the following.

c1 = super(C, C)
c2 = super(C, C)
print(c1 is c2)
print(c1 == c2)
print(c1.func is c2.func)
print(c1.func == c2.func)

Output:

False
False
True
True

 c1 and c2 is not an object, but their approach is the same.

That  super (C, C) .func  and  super (C, c_obj) .func  indeed different. Then print out and see what's the difference:

print(super(C, C).func)
print(super(C, c_obj).func)

 Output:

<function A.func at 0x0000000009F4D6A8>
<bound method A.func of <__main__.C object at 0x00000000022A94E0>>

 passing super second parameter is the class, a function is obtained.

 a super second argument is the object, is obtained binding method.

 The difference between function and binding methods will not repeat them here want the same results, just give function to pass a parameter, and the binding method you do not need to pass additional parameters of.

print(super(C, C).func(c_obj))
print(super(C, c_obj).func())

 Output:

from A
from A

I now summarize:

  1. super () when in use need to pass two parameters can be omitted in the class, we use the super () method of the parent class or a sibling class come;
  2. super () is calculated according to the MRO second parameter, the first search method according to a sequence parameter class.
  3. super () the second parameter is based, is a function obtained by the method, parameters used to pass self. The second parameter is the object, is obtained binding method, does not require re-transmission of the self parameter.

Some suggestions to use super () is:

  1. The method of super () call to exist;
  2. When the transmission parameters, and to make use of * args ** kwargs;
  3. The parent class of some of the features, such as [], rewritten __getattr __, super objects can not be used.
  4. super () The second parameter passed is class, class methods and static methods recommended that the parent class is called.

Guess you like

Origin www.cnblogs.com/taosiyu/p/11343639.html