Chuan Chi podcast MRO order multiple inheritance and study notes

1. call parent class method alone

# coding=utf-8

print("******多继承使用类名.__init__ 发生的状态******")
class Parent(object):
    def __init__(self, name):
        print('parent的init开始被调用')
        self.name = name
        print('parent的init结束被调用')

class Son1(Parent):
    def __init__(self, name, age):
        print('Son1的init开始被调用')
        self.age = age
        Parent.__init__(self, name)
        print('Son1的init结束被调用')

class Son2(Parent):
    def __init__(self, name, gender):
        print('Son2的init开始被调用')
        self.gender = gender
        Parent.__init__(self, name)
        print('Son2的init结束被调用')

class Grandson(Son1, Son2):
    def __init__(self, name, age, gender):
        print('Grandson的init开始被调用')
        Son1.__init__(self, name, age)  # 单独调用父类的初始化方法
        Son2.__init__(self, name, gender)
        print('Grandson的init结束被调用')

gs = Grandson('grandson', 12, '男')
print('姓名:', gs.name)
print('年龄:', gs.age)
print('性别:', gs.gender)

print("******多继承使用类名.__init__ 发生的状态******\n\n")

operation result:

******多继承使用类名.__init__ 发生的状态******
Grandson的init开始被调用
Son1的init开始被调用
parent的init开始被调用
parent的init结束被调用
Son1的init结束被调用
Son2的init开始被调用
parent的init开始被调用
parent的init结束被调用
Son2的init结束被调用
Grandson的init结束被调用
姓名: grandson
年龄: 12
性别: 男
******多继承使用类名.__init__ 发生的状态******

2. multiple inheritance method is overridden to call something a parent class super

print("******多继承使用super().__init__ 发生的状态******")
class Parent(object):
    def __init__(self, name, *args, **kwargs):  # 为避免多继承报错,使用不定长参数,接受参数
        print('parent的init开始被调用')
        self.name = name
        print('parent的init结束被调用')

class Son1(Parent):
    def __init__(self, name, age, *args, **kwargs):  # 为避免多继承报错,使用不定长参数,接受参数
        print('Son1的init开始被调用')
        self.age = age
        super().__init__(name, *args, **kwargs)  # 为避免多继承报错,使用不定长参数,接受参数
        print('Son1的init结束被调用')

class Son2(Parent):
    def __init__(self, name, gender, *args, **kwargs):  # 为避免多继承报错,使用不定长参数,接受参数
        print('Son2的init开始被调用')
        self.gender = gender
        super().__init__(name, *args, **kwargs)  # 为避免多继承报错,使用不定长参数,接受参数
        print('Son2的init结束被调用')

class Grandson(Son1, Son2):
    def __init__(self, name, age, gender):
        print('Grandson的init开始被调用')
        # 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍
        # 而super只用一句话,执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因
        # super(Grandson, self).__init__(name, age, gender)
        super().__init__(name, age, gender)
        print('Grandson的init结束被调用')

print(Grandson.__mro__)

gs = Grandson('grandson', 12, '男')
print('姓名:', gs.name)
print('年龄:', gs.age)
print('性别:', gs.gender)
print("******多继承使用super().__init__ 发生的状态******\n\n")

operation result:

******多继承使用super().__init__ 发生的状态******
(<class '__main__.Grandson'>, <class '__main__.Son1'>, <class '__main__.Son2'>, <class '__main__.Parent'>, <class 'object'>)
Grandson的init开始被调用
Son1的init开始被调用
Son2的init开始被调用
parent的init开始被调用
parent的init结束被调用
Son2的init结束被调用
Son1的init结束被调用
Grandson的init结束被调用
姓名: grandson
年龄: 12
性别: 男
******多继承使用super().__init__ 发生的状态******

note:

  1. Two or more different result code execution
  2. If the two sub-classes inherit the parent class, subclass when the parent class name by calling, parent be executed twice
  3. If the two sub-classes inherit the parent class, when in a subclass by calling super, parent be carried out once

3. Single inheritance super


print("******单继承使用super().__init__ 发生的状态******")
class Parent(object):
    def __init__(self, name):
        print('parent的init开始被调用')
        self.name = name
        print('parent的init结束被调用')

class Son1(Parent):
    def __init__(self, name, age):
        print('Son1的init开始被调用')
        self.age = age
        super().__init__(name)  # 单继承不能提供全部参数
        print('Son1的init结束被调用')

class Grandson(Son1):
    def __init__(self, name, age, gender):
        print('Grandson的init开始被调用')
        super().__init__(name, age)  # 单继承不能提供全部参数
        print('Grandson的init结束被调用')

gs = Grandson('grandson', 12, '男')
print('姓名:', gs.name)
print('年龄:', gs.age)
#print('性别:', gs.gender)
print("******单继承使用super().__init__ 发生的状态******\n\n")

to sum up

  1. super () .__ init__ with respect to the class name .__ init__, in succession on a single use substantially no difference
  2. But there are differences in the multiple inheritance, super method to ensure that each parent class's method only once, and the class name of the method causes method is executed multiple times, specifically to see the results of previous output
  3. When multiple inheritance, use the super method of transmission parameters parent class, the reason should be because the python algorithm resulting in super, all the parameters must be passed, otherwise it will error
  4. When single inheritance, the use of super method, you can not transfer all, you can only pass the required parameters parent class method, otherwise it will error
  5. When multiple inheritance, with respect to the class name .__ init__ method, each parent should all write again, and use the super method, just write a word they all perform the method of the parent class, which is why all the required multiple inheritance one reason for parameter passing

By super () function may be implemented to skip some of the steps will be performed by.

Small scale chopper (hereinafter interview questions)

What is the output of the following code will be? Speak your answers and explanations.

class Parent(object):
    x = 1

class Child1(Parent):
    pass

class Child2(Parent):
    pass

print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Parent.x = 3
print(Parent.x, Child1.x, Child2.x)

The answer, output of the code is:

1 1 1
1 2 1
3 2 3

Make you confused or surprised about is the last line of output is 323 instead of 321. Why change the value Parent.x change Child2.x value will be, but at the same Child1.x values ​​have not changed?

The key to this answer is that in Python, class variables are internally handled as a dictionary. If a variable name is not found in the current class dictionary, the search for ancestors (such as parent) until the variable name referenced is found (variable names if the referenced neither nor ancestor in the class where their class find, it will lead to a AttributeError exception).

Thus, x = 1 will set the variable x has a value such that the class 1 and the class referenced in any subclass thereof in the parent class. This is because the output of the first print statement is 111.

Subsequently, if any of its subclasses the override value (e.g., we execute the statement Child1.x = 2), then the value is changed only in the subclass. This is why the output of the second print statement is 121.

Finally, if the value is changed in the parent class (e.g., we execute the statement Parent.x = 3), this change will affect any of the sub-subclass values ​​among values ​​not rewritten (in this example is the influence of class is Child2). This is why the third print output is 323.

Published 655 original articles · won praise 206 · views 890 000 +

Guess you like

Origin blog.csdn.net/moonlightpeng/article/details/104082537