super()函数的使用

本文深入探讨Python中的super()函数,解释其与MRO列表的关系,以及如何在多重继承中正确使用super(),避免代码重复,实现优雅的继承扩展。
部署运行你感兴趣的模型镜像

@(python进阶)[super, 继承, mro]


018.11.10

说明

一些Python入门书并没有讲清楚super()函数应该怎么用,只在说继承知识点的时候顺便一笔带过。为此我糊涂了好久、好久……

继承

Python中的继承很容易实现,如下:

class A(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def greet(self):
        print("I'm A")

    def show(self):
        
        string = ("My name is {name}.\n"
                  "I'm {age}.".format(name=self.name, age=self.age))
        print(string)


class B(A):
    pass


if __name__ == "__main__":
    b = B("Guan", 18)
    b.greet()
    b.show()

# 输出:
I'm A
My name is Guan.
I'm 18.

所以继承父类的时候,super()函数并非必要

那什么时候确切的要用到super()呢?
答:欲求不满时。

使用super()

之所以需要“继承”,大部分原因是我们想要扩展基础类——需要派生类有更多的功能。当然了,如果只是额外增加一个“独立”功能,仍然用不到super()。如下:

class A(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def greet(self):
        print("I'm A")

    def show(self):
        
        string = ("My name is {name}.\n"
                  "I'm {age}.".format(name=self.name, age=self.age))
        print(string)


class B(A):
    # “独立”功能
    def cry(self):
        print("cry ...")


if __name__ == "__main__":
    b = B("Guan", 18)
    b.cry()

# 输出:
cry ... 

B类中的cry()是一个与A类完全无关的函数,所以直接定义就OK。但此时需求变了,我们需要B类的对象可以在自我介绍的时候先说hello。我们当然可以用如下方式重载show():

class B(A):
    def show(self):
        print("ya~hello~")
        string = ("My name is {name}.\n"
                  "I'm {age}.".format(name=self.name, age=self.age))
        print(string)

可这样做重复了A中的部分代码,很不“程序员”。所以super()出场了:

class B(A):
    def show(self):
        print("ya~hello~")
        super().show()

但python2中需要这样写:

class B(A):
    def show(self):
        print("ya~hello~")
        super(B, self).show()  # 需要传入自己的类名以及对象self

乍一看super()的意思是:获取父类。而super().show()就是调用父类的show()函数。是,也不是

真实的super()

super()获取的是MRO列表中下一个类。什么是MRO呢?这里不是重点,它有自己计算的方式,有兴趣可以自己找找资料。

示例:

class A(object):
    pass

class B(A):
    pass

if __name__ == "__main__":
	print(B.mro())

输出内容如下:
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

在MRO列表中,B的下一个类是A。所以在B类中的super(),代表A。这里刚好A是B的父类。也有不刚好的时候。

class A(object):
    def __init__(self):
        print("A")
        super().__init__()


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().__init__()


if __name__ == "__main__":
    d = D()
    print(D.mro())

# 输出:
D
B
C
A
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

注意ABCD的输出顺序。可以看到,B中调用super().__init__(),没有打印“A”,而是“C”,这是符合MRO列表顺序的。

总结

  • super()与父类没有直接关系
  • super()获取的是MRO列表中下一个类

感谢

参考个人博客 FunHacks
https://funhacks.net/explore-python/Class/super.html
参考慕课老师 bobby
https://www.bilibili.com/video/av28281876/?p=22

您可能感兴趣的与本文相关的镜像

Langchain-Chatchat

Langchain-Chatchat

AI应用
Langchain

Langchain-Chatchat 是一个基于 ChatGLM 等大语言模型和 Langchain 应用框架实现的开源项目,旨在构建一个可以离线部署的本地知识库问答系统。它通过检索增强生成 (RAG) 的方法,让用户能够以自然语言与本地文件、数据库或搜索引擎进行交互,并支持多种大模型和向量数据库的集成,以及提供 WebUI 和 API 服务

评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值