python 中的 super详解

yizhihongxing

Python 中的 super 详解

Python 的 super 函数是一种很特殊和重要的方法,它允许派生类调用父类的方法、属性等,本文将详细讲解 super 函数的用法及其机制。

什么是 super 函数

super 函数是 Python 中的一个内置函数,它常用于在派生类中调用其基类的方法或属性。通过 super 函数,我们可以更加方便地实现派生类与基类之间的联系,同时避免了硬编码所带来的各种问题。

super 函数的用法

super 函数最常见的用法就是调用父类的方法,其调用方式可以有两种:

  • 显式调用
  • 隐式调用

显式调用

通过显式调用 super 函数,我们可以直接指定要调用的基类和方法。例如:

class Base:
    def __init__(self):
        self.name = 'Base'

    def show(self):
        print(f'I am {self.name}')

class Derived(Base):
    def __init__(self):
        super(Derived, self).__init__()
        self.name = 'Derived'

    def show(self):
        print(f'I am {self.name}')

        # 调用 Base 类的 show 方法
        super(Derived, self).show()

在上面的示例中,Derived 类继承自 Base 类,并重写了 show 方法。在 Derived 的 show 方法中,我们通过显式调用 super 函数来调用 Base 类的 show 方法,从而实现了在派生类中调用其基类的方法。

隐式调用

通过隐式调用 super 函数,Python 会自动查找当前类的 MRO(Method Resolution Order)列表,并调用第一个碰到的基类的方法。例如:

class A:
    def show(self):
        print('A')

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

class C(A):
    def show(self):
        print('C')

class D(B, C):
    pass

d = D()
d.show()

在上面的示例中,D 类继承自 B 和 C 两个类。当我们调用 d.show() 方法时,Python 会自动去查找 D 的 MRO 列表,发现 B 是其第一个基类,在执行 B 的 show 方法时,又调用了 super().show(),此时 Python 会去查找 D 的 MRO 列表中的下一个基类 C,执行 C 的 show 方法。因此最终输出结果为:

B
C

super 函数的机制

super 函数实际上是通过 C 语言实现的(这就是为什么它如此高效)。

在 Python 中,每个类都有一个 MRO(Method Resolution Order)列表,它表示了 Python 在调用该类的方法时会按照顺序搜索的列表。MRO 列表主要是通过 C3 算法来计算的,其规则如下:

  1. 如果 A 是 B 的父类,则 A 在 B 的前面;
  2. 如果 A 和 B 是同一级别的类,且 A 在 B 前面出现在 MRO(这通常是在多重继承的情况下);
  3. 如果存在多个父类同时满足以上两个条件,则按照定义时的顺序加入 MRO。

例如,如果我们有一个如下所示的类继承关系:

class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

其 MRO 列表将按照顺序排列为 [D, B, C, A]

在 Python 2.x 版本中,我们需要手动指定调用的父类方法,例如 super(Derived, self);而在 Python 3.x 中,我们可以不传入任何参数,例如 super(),Python 会自动查找当前类的子类并调用对应的方法。实际上,这有助于解决由于硬编码所带来的各种问题。

总结

super 函数是 Python 编程中一个非常重要的函数,它可以帮助我们在派生类中调用其基类的方法,并避免硬编码所带来的各种问题。通过显式调用或隐式调用 super 函数,我们可以更加方便地实现 Python 的多重继承机制。

例如,通过在派生类 Derived 中调用 super().__init__() 方法,我们可以方便地初始化其基类 Base 中的变量;而通过在多重继承时使用 super 函数,我们可以更好地控制派生类和基类中的方法的运行顺序,从而避免出现预料之外的错误。

示例说明

这里提供两个超级函数的示例说明,可以更好地理解 super 函数的用法和机制。

示例一

下面这个示例演示了在 Python 2.x 中使用 super 函数的方法,它可以解决菱形继承所带来的问题。在 Python 2.x 中,我们需要手动指定调用的父类方法,例如 super(Derived, self)

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

class B(A):
    pass

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

class D(B, C):
    pass

d = D()

输出结果为:

C.__init__
A.__init__

在这个示例中,我们定义了四个类:ABCD,其中 BC 都继承自 A。在 C 类中,我们重写了 __init__ 方法,并在其中通过 super(C, self).__init__() 显式调用父类 A__init__ 方法。当我们创建 D 的实例时,Python 会自动调用 D 中的 __init__ 方法,并通过 MRO 列表执行 C 中的 __init__ 方法,最终输出正确结果。

示例二

下面的示例演示了在多重继承情况下,通过使用 super 函数可以更好地控制基类的方法调用顺序。

class A:
    def show(self):
        print('A')

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

class C(A):
    def show(self):
        print('C')
        super().show()

class D(B, C):
    pass

d = D()
d.show()

输出结果为:

B
C
A

在这个示例中,D 类继承自 BC,并分别重写了 show 方法。在 BCshow 方法中,我们都使用了 super() 来调用基类 Ashow 方法。当我们创建 D 的实例并调用 show 方法时,Python 会按照 MRO 列表的顺序,从 D 开始先调用 Bshow 方法,再调用 Cshow 方法,最后调用基类 Ashow 方法。因此,最终输出结果为 B C A

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python 中的 super详解 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Android如何实现年月选择器功能

    Android如何实现年月选择器功能 在Android应用中实现年月选择器功能可以通过以下步骤完成: 步骤1:创建布局文件 首先,我们需要创建一个布局文件来显示年月选择器。可以使用DatePicker控件来实现这个功能。在布局文件中添加以下代码: <DatePicker android:id=\"@+id/datePicker\" …

    other 2023年8月24日
    00
  • 详解JavaScript之ES5的继承

    详解JavaScript之ES5的继承 JavaScript是一种弱类型、基于原型的语言,它的继承机制跟其他面向对象语言不一样。在ES5中,可以使用以下几种方式实现继承: 1. 原型链继承 原型链继承是利用原型链中的关系进行继承,通过将父类的实例作为子类的原型,让子类实例可以访问父类实例上的属性和方法。但是它也有一些缺点,例如原型中的引用类型属性是共享的,子…

    other 2023年6月27日
    00
  • javascript入门之string对象【新手必看】

    接下来我将详细讲解“JavaScript入门之String对象【新手必看】”的完整攻略。 1. 什么是String对象 String对象是JavaScript中表示文本的类型。它是一组字符的有序序列,每个字符都有一个数字索引,这个索引从0开始,以字符串的长度减1结束。String对象有许多重要的属性和方法,可以让我们方便地处理文本数据。 2. 如何创建Str…

    other 2023年6月20日
    00
  • Python子类继承父类构造函数详解

    Python子类继承父类构造函数详解 在Python的类继承中,子类可以继承父类的构造函数。本攻略将详细介绍Python子类继承父类构造函数的相关知识。 什么是构造函数? 构造函数是Python中的一种特殊函数,用于在对象创建时进行初始化操作。通常,构造函数的名称为__init__,并且该函数会自动调用。 下面是一个简单的类定义,该类包含一个构造函数: cl…

    other 2023年6月26日
    00
  • win10常见问题有哪些?win10常见问题及解决方法汇总

    Win10 常见问题及解决方法汇总 问题一:更新失败又失败 问题描述 用户在尝试更新 Windows 10 操作系统时,多次失败且没有任何提示消息。 解决方法 清空软件分发目录(Software Distribution)缓存。 打开“命令提示符”(管理员身份)。 输入“net stop wuauserv”,回车,停止Windows更新服务。 执行命令“re…

    other 2023年6月27日
    00
  • 微信小程序全局变量改变监听的实现方法

    微信小程序全局变量改变监听的实现方法攻略 在微信小程序中,要实现全局变量的改变监听,可以通过以下步骤进行操作: 步骤一:创建全局变量 首先,在小程序的app.js文件中创建一个全局变量,可以使用getApp()方法获取小程序实例,并在实例中定义全局变量。例如: // app.js App({ globalData: { count: 0 } }) 在上述示例…

    other 2023年7月29日
    00
  • win10系统下如何使用dns优选工具

    Win10系统下如何使用DNS优选工具攻略 DNS(Domain Name System)是一种用于将域名转换为IP地址的协议。在访问网站时,计算机需要通过DNS服务器将域名解析为IP地址。攻略将介绍如何使用DNS优选工具来优化DNS服务器的选择,提高网络访问速度。 步骤1:下载DNS优工具 可以在网上下载DNS优选工具,例如DNS Jumper、Quick…

    other 2023年5月7日
    00
  • springboot application.properties 文件注入数组方式

    下面我将为你讲解详细的Spring Boot application.properties文件注入数组方式的攻略。 1. 基本概念 在Spring Boot中,我们可以通过配置文件(application.properties或application.yml)配置应用程序的属性,属性可以注入到Java代码中。数组是一种特殊的属性类型,如果要将数组注入到应用程…

    other 2023年6月25日
    00
合作推广
合作推广
分享本页
返回顶部