Python - 面向对象编程 - super() (下)

简介: Python - 面向对象编程 - super() (下)
from threading import Thread
class MyThread(Thread):
    def __init__(self, name):
        # 1、实现子类独有功能
        print("子类线程 %s" % name)
        # 2、需要依赖父类方法完成其他功能
        super().__init__(name=name)


多继承中使用 super


类图

image.png


实际代码

# 多继承
class Animal:
    def __init__(self, animalName):
        print(animalName, 'is an animal.')
# Mammal 继承 Animal
class Mammal(Animal):
    def __init__(self, mammalName):
        print(mammalName, 'is a mammal.')
        super().__init__(mammalName)
# CannotFly 继承 Mammal
class CannotFly(Mammal):
    def __init__(self, mammalThatCantFly):
        print(mammalThatCantFly, "cannot fly.")
        super().__init__(mammalThatCantFly)
# CannotSwim 继承 Mammal
class CannotSwim(Mammal):
    def __init__(self, mammalThatCantSwim):
        print(mammalThatCantSwim, "cannot swim.")
        super().__init__(mammalThatCantSwim)
# Cat 继承 CannotSwim 和 CannotFly
class Cat(CannotSwim, CannotFly):
    def __init__(self):
        print('I am a cat.');
        super().__init__('Cat')
# Driver code
cat = Cat()
print('')
bat = CannotSwim('Bat')
# 输出结果
I am a cat.
Cat cannot swim.
Cat cannot fly.
Cat is a mammal.
Cat is an animal.
Bat cannot swim.
Bat is a mammal.
Bat is an animal.


好像挺奇怪的,从输出结果看,为什么 CannotSwim 类里面的 super().__init__() 调用的是 CannotFly 类里面的方法呢?不是应该调用 CannotSwim 的父类 Mamal 的方法吗?

 

灵魂拷问二:super 的执行顺序到底是什么?

  • 其实 super() 并不一定调用父类的方法
  • super() 是根据类的 MRO 方法搜索顺序来决定调用谁的
  • super() 真正调用的是 MRO 中的下一个类,而不一定是父类
  • 当然,这种情况只会出现在多继承

先来看看 Cat 的 MRO

print(Cat.__mro__)


(<class'__main__.Cat'>, <class'__main__.CannotSwim'>, <class'__main__.CannotFly'>, <class'__main__.Mammal'>, <class'__main__.Animal'>, <class'object'>)

从 Cat 的 MRO 可以看到

  • CannotSwim 后面跟的是 CannotFly 而不是 Mamal
  • 所以 CannotSwim 类里面的 super() 会调用 CannotFly 里面的方法

 

多继承的栗子二

实际代码

class A:
    def __init__(self):
        self.n = 2
    def add(self, m):
        # 第四步
        # 来自 D.add 中的 super
        # self == d, self.n == d.n == 5
        print('self is {0} @AAA.add'.format(self))
        self.n += m
        # d.n == 7
class C(A):
    def __init__(self):
        self.n = 4
    def add(self, m):
        # 第三步
        # 来自 B.add 中的 super
        # self == d, self.n == d.n == 5
        print('self is {0} @CCC.add'.format(self))
        # 等价于 suepr(C, self).add(m)
        # self 的 MRO 是 [D, B, C, A, object]
        # 从 C 之后的 [A, object] 中查找 add 方法
        super().add(m)
        # 第五步
        # d.n = 7
        self.n += 4
        # d.n = 11
class B(A):
    def __init__(self):
        self.n = 3
    def add(self, m):
        # 第二步
        # 来自 D.add 中的 super
        # self == d, self.n == d.n == 5
        print('self is {0} @BBB.add'.format(self))
        # self 的 MRO 是 [D, B, C, A, object]
        # 从 B 之后的 [C, A, object] 中查找 add 方法
        # 从 C 找 add 方法
        super().add(m)
        # 第六步
        # d.n = 11
        self.n += 3
        # d.n = 14
class D(B, C):
    def __init__(self):
        self.n = 5
    def add(self, m):
        # 第一步
        print('self is {0} @DDD.add'.format(self))
        # self 的 MRO 是 [D, B, C, A, object]
        # 从 D 之后的 [B, C, A, object] 中查找 add 方法
        # 从 B 找 add 方法
        super().add(m)
        # 第七步
        # d.n = 14
        self.n += 5
        # self.n = 19
d = D()
d.add(2)
print(d.n)


先看看 D 类的 MRO

print(D.__mro__)


(<class'__main__.D'>, <class'__main__.B'>, <class'__main__.C'>, <class'__main__.A'>, <class'object'>)

 

输出结果

self is <__main__.D object at 0x10c14a190> @DDD.add
self is <__main__.D object at 0x10c14a190> @BBB.add
self is <__main__.D object at 0x10c14a190> @CCC.add
self is <__main__.D object at 0x10c14a190> @AAA.add
19


调用顺序的确是 D、B、C、A

 

执行顺序

class D(B, C):          class B(A):            class C(A):             class A:
    def add(self, m):       def add(self, m):      def add(self, m):       def add(self, m):
        super().add(m)  1.--->  super().add(m) 2.--->  super().add(m)  3.--->  self.n += m
        self.n += 5   <------6. self.n += 3    <----5. self.n += 4     <----4. <--|
        (14+5=19)               (11+3=14)              (7+4=11)                (5+2=7)


执行顺序图

image.png


super() 的注意事项


https://www.cnblogs.com/poloyy/p/15236135.html  


相关文章
|
4天前
|
Python
python基础篇:面向对象编程
python基础篇:面向对象编程
21 0
|
4天前
|
Python
【Python进阶(三)】——面向对象编程
【Python进阶(三)】——面向对象编程
|
4天前
|
Python
Python中的面向对象
【5月更文挑战第4天】面向对象编程(OOP)是Python的核心,涉及类与对象、封装、继承和多态。类是对象的模板,对象则是类的实例。例如,`Person`类有`__init__`构造方法和`greet`方法。
15 3
|
4天前
|
算法 Java 程序员
[重学Python] Day6 面向对象编程 基础
面向对象编程基础讲解,包括类与对象的概念,类是对象的模板,对象是类的实例。Python中使用`class`定义类,通过`__init__`初始化对象。创建对象并调用方法如`drive`和`target_client`。访问权限在Python中相对宽松,使用单下划线表示受保护的属性。面向对象的三大支柱是封装、继承和多态,封装是隐藏实现细节,仅暴露简单接口。提供了数字时钟和平面上的点的类定义作为练习示例。
14 0
|
4天前
|
算法 Python
Python面向对象oop编程(二)
Python面向对象oop编程(二)
|
4天前
|
运维 算法 Shell
第六章 Python类(面向对象编程)
第六章 Python类(面向对象编程)
|
4天前
|
Python
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
|
4天前
|
设计模式 算法 程序员
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
|
4天前
|
数据安全/隐私保护 Python
Python从入门到精通——2.2.1深入学习面向对象编程:类和对象的定义
Python从入门到精通——2.2.1深入学习面向对象编程:类和对象的定义
|
4天前
|
数据安全/隐私保护 Python
python基础之面向对象
面向对象编程(OOP)是一种以对象为中心的编程范式,通过对象和类实现现实世界的抽象。对象是程序的基本单元,类是对象的模板。主要特点包括:封装,通过访问修饰符隐藏对象内部细节,保证数据安全;继承,子类继承父类属性和方法,实现代码复用;多态,同方法调用在不同对象上产生不同行为,增强灵活性。示例代码展示了Python中的类定义、封装、继承和多态概念。