我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python中类的mro与继承关系详解(二)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python中类的mro与继承关系详解(二)

前言

版本:

  • windows 10.0
  • python 3.8

多重继承

在Python数字比较与类结构中有简略提到类,且在Python中类的mro与继承关系详解稍有解释继承关系,用到一个基类Animal如下:

class Animal:
    property_ = '能够思考'

    def __init__(self, name, age, value):
        self.name_ = name
        self.age_ = age
        self.val_ = val

再定义Action活动作为另一个基类:

class Action:

    def __init__(self, action, val):
        self.action_ = action
        self.val_ = val
  • 现在需定义一个Dog类,不仅是动物,还能够跑,可以来继承上面两个类来定义:
class Dog(Animal, Action):

    def __init__(self, name, age, action, val):
        Animal.__init__(self, name, age, val+1)
        Action.__init__(self, action, val)

dog = Dog('大福', 8, '跑', 78)
print(dog.__dict__)
# {'name_': '大福', 'age_': 8, 'val_': 78, 'action_': '跑'}

发现打印出的实例属性,好像字典的键值更新,先初始化Animal时,val传入的值为79,而后被更新为78,这里为什么不能像继承单个类一样直接用super方法代替呢。

上一篇有提到mro解析顺序,可进行尝试,不重写__init__方法,发现Dog类只能传入三个参数,且都为Animal类的参数,因为继承的两个父类都有该方法,优先继承左边的父类方法,如果想都继承可以考虑这样的形式,然而会提高后续维护的困难性。

可以将最左边的父类改成super方式:

class Dog(Animal, Action):

    def __init__(self, name, age, action, val):
        super().__init__(name, age, val+1)
        Action.__init__(self, action, val)

mro解析顺序,与上面所述一致:

Dog.mro()
# [__main__.Dog, __main__.Animal, __main__.Action, object]
  • 祖孙类

如再进行继承,视Dog为父类,其Animal,Action都为祖父类,定义一个Pet类:

class Pet(Dog):
    pass
pet = Pet('大福', 8, '跑', 78)

传入参数,和实例化的对象跟Dog一样,如果需要改写某个方法,可以参照之前的方法进行改写,另外若在保留原方法的逻辑上进行补充则用super方法。

Pet类的mro:

Pet.mro()
# [__main__.Pet, __main__.Dog, __main__.Animal, __main__.Action, object]

思考片刻

通过上面的继承及对应的mro解析顺序,可以思考以下通过多重继承类后,输出的x属性值为多少:

class Alpha:
    def __init__(self, val):
        self.x = val

class Beta(Alpha):
    pass

class Gamma:
    def __init__(self, val):
        self.x = val + 1
class Omega(Gamma):
    def __init__(self, val):
        super().__init__(val + 1)
class Kappa(Beta, Omega):
    pass
k = Kappa(1)
print(k.x)

如果脑内没有一个mro解析顺序图,这里准备了:

[__main__.Kappa, __main__.Beta, __main__.Alpha, __main__.Omega, __main__.Gamma, object]

这里或许会有疑问,Beta后面不是Omega吗?怎么到Alpha了,可以先看下Omega,继承Gamma,而GammaAlpha并不是同源的,类似于Dog类的继承,那么优先就会使用Alpha的__init__方法,所以在传入参数值1的时候,仅运行了Alpha内的self.x = val,属性x被赋值成1,在最后print输出即为1,打印结果检查:

print(k.x)
# 1

若把Gamma类改成继承Alpha类,再次猜测print(k.x)的值为多少?

class Alpha:
    def __init__(self, val):
        self.x = val

class Beta(Alpha):
    pass

class Gamma(Alpha):
    def __init__(self, val):
        self.x = val + 1

class Omega(Gamma):
    def __init__(self, val):
        super().__init__(val + 1)

class Kappa(Beta, Omega):
    pass

k = Kappa(1)
print(k.x)

查看mro解析顺序:

[__main__.Kappa, __main__.Beta, __main__.Omega, __main__.Gamma, __main__.Alpha, object]

此时发现Alpha解析优先级排在最后,BetaOmega可以看做是BetaGamma的优先级比较,因为Omega继承Gamma,且重写了__init__方法,所以当传入参数时会对Gamma类的属性进行赋值,虽然Beta类直接继承Alpha,但Gamma类也直接继承,所以Alpha解析顺序需要排在Gamma后面,从而当Kappa类传入参数时,经过Omega的super加1,传入到Gamma处时为:self.x = val + 1中的val为2,输出的k.x的值即为3,查看打印结果:

print(k.x)
# 3

总结

通过连续两篇对类继承及mro解析顺序的说明,理解类在多重继承中的变化,无论继承多少遍,总归要回归本心,但也不能胡乱继承,有条理的,有意义的继承,才能让自己乃至他人更好理解当下写出的类。

到此这篇关于Python中类的mro与继承关系详解的文章就介绍到这了,更多相关Python mro内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python中类的mro与继承关系详解(二)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python 类的继承实例详解

Python 类的继承详解 Python既然是面向对象的,当然支持类的继承,Python实现类的继承比JavaScript简单。 Parent类:class Parent: parentAttr = 100 def __init__(sel
2022-06-04

python类的继承实例详解

python 类的继承 对于许多文章讲解python类的继承,大多数都是说一些什么oop,多态等概念,我认为这样可能对有一定基础的开发者帮助不是那么大,不如直接用在各种情况下所写的代码,来展示对于某一种代码情况,代码运行会有什么效果。这样可
2022-06-04

详解Java语言中的抽象类与继承

这篇文章主要为大家详细介绍了Java语言中的抽象类与继承的相关资料,文中的示例代码讲解详细,对我们学习Java有一定的帮助,感兴趣的小伙伴快跟随小编一起了解一下
2022-11-13

C++ 函数继承详解:如何使用 RTTI 来检查类型继承关系?

rtti 是一种机制,允许您在运行时检查类型的继承关系。使用 rtti,您可以获取有关对象的类型信息,这对于验证继承关系非常有用。要检查继承关系,请使用 typeid 运算符获取对象的类型信息。要进行动态转换,请使用 dynamic_cas
C++ 函数继承详解:如何使用 RTTI 来检查类型继承关系?
2024-05-03

C++ 函数继承详解:如何理解继承中的“is-a”和“has-a”关系?

C++ 函数继承详解:掌握“is-a”和“has-a”关系什么是函数继承?函数继承是 C++ 中一种将派生类中定义的方法与基类中定义的方法关联起来的技术。它允许派生类访问和重写基类的方法,从而扩展了基类的功能。“is-a”和“has-
C++ 函数继承详解:如何理解继承中的“is-a”和“has-a”关系?
2024-05-02

C++ 函数继承详解:如何处理继承中出现的二义性?

解决继承中的二义性存在同名函数时,可以通过以下方法解决二义性:使用作用域解析符(::)指定函数所属的类。在派生类中重写基类函数。创建基类指针并指向派生类对象,然后使用指针调用基类函数。C++ 函数继承详解:处理继承中的二义性继承中的二义性
C++ 函数继承详解:如何处理继承中出现的二义性?
2024-04-30

怎么理解python 经典类与新式类的继承

怎么理解python 经典类与新式类的继承,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。例子1:class a: def p(self):
2023-06-04

Python中类继承与多态的示例分析

这篇文章主要介绍了Python中类继承与多态的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。概念类(Class): 用来描述具有相同的属性和方法的对象的集合。类变量:
2023-06-22

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录