方法的解析顺序表

知识点

背景

  1. 调用父类方法的几种方式
    • 继承的父类名.方法(self, 参数)
    • super().方法(参数)
    • super(继承的父类名, self).方法(参数)

父类名.方法(self, 参数)

1
2
3
4
5
6
7
8
9
10
class Parent(Object):

def __init__(self, age, name):
pass

class Son1(Parent):

def __init__(self, age, name):
Parent.__init__(self, age, name)
pass

缺点:这种方式对于多继承可能会产生多次调用爷爷级别的继承类

super().方法(参数)

1
2
3
4
5
6
7
8
9
10
class Parent(Object):

def __init__(self, age, name):
pass

class Son1(Parent):

def __init__(self, age, name):
super().__init__(age, name)
pass

备注:这种方式创建的对象中继承类的顺序是按照【对象名.__mro__】返回值的顺序调用的,使用它可以一次性调用所有继承的父类。

super(继承的父类名, self).方法(参数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Parent(Object):

def __init__(self, age, name):
pass

class Parent1(Object):

def __init__(self):
pass

class Son1(Parent, Parent1):

def __init__(self, age, name):
# super中填写的是哪个类,则调用类方法时从__mro__返回值中该元素之后的一个元素开始实例化
super(Parent1, self).__init__(age, name)
pass

备注:这类方式可以决定调用被继承父类方法的优先级,同时也可以决定不调用被继承其它父类的方法

其它

  1. 对象名.__mro__:

    通过该方法可以打印出当前对象中调用的所有的父类、父类被调用的顺序。它的实现是通过c3算法实现,返回值是调用的类的元组

  2. 多继承中父类方法调用顺序

    根据【对象名.__mro__】返回的元组信息(b),我们将实例化对象的类名(a)拿到元组b中依次进行比对,当其中一个符合时就会调用紧跟该类中的下一个类名,直至结束

类属性的寻找顺序

在Python中,类变量在内部是作为字典处理的。如果一个变量的名字没有在当前类的字典中发现,则将搜索祖先类(比如父类)直到被引用的变量名被找到,如果这个变量名既没有在当前类中被寻找到,也没有祖先类中被找到,则会返回一个Attribute异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Parent(Object):
x = 1

class Son(Parent):
pass

class Son1(Parent):
pass

print(Parent.x, Son.x, Son1.x)
Son.x = 2
print(Parent.x, Son.x, Son1.x)
Parent.x = 3
print(Parent.x, Son.x, Son1.x)

# 上述内容的返回结果为
1 1 1
1 2 1
3 2 3

作业

  1. (问答)请简述在子类中调用父类方法的三种方式
  2. (问答)通过【继承的父类名.方法(self, 参数)】这种方式调用父类的方法,存在的问题是什么?
  3. (问答)通过【super().方法(参数)】方式调用父类的方法,它父类的调用顺序是什么样的
  4. (问答)通过【super(继承的父类名, self).方法(参数)】方式调用父类的方法,它父类的调用顺序是什么样的
  5. 打印出当前对象中调用的父类方法
  6. (问答)请简述类属性在类中的查找顺序