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

 更新时间:2022年07月28日 08:48:38   作者:​ 宿者朽命  ​  
这篇文章主要介绍了Python中类的mro与继承关系详解,上一篇我们已经通过mro相关资料介绍了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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python之tensorflow手把手实例讲解猫狗识别实现

    python之tensorflow手把手实例讲解猫狗识别实现

    要说到深度学习图像分类的经典案例之一,那就是猫狗大战了。猫和狗在外观上的差别还是挺明显的,无论是体型、四肢、脸庞和毛发等等, 都是能通过肉眼很容易区分的。那么如何让机器来识别猫和狗呢?网上已经有不少人写过这案例了,我也来尝试下练练手。
    2021-09-09
  • Python用requests库爬取返回为空的解决办法

    Python用requests库爬取返回为空的解决办法

    这篇文章主要介绍了Python用requests库爬取返回为空的解决办法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • Python Scrapy框架:通用爬虫之CrawlSpider用法简单示例

    Python Scrapy框架:通用爬虫之CrawlSpider用法简单示例

    这篇文章主要介绍了Python Scrapy框架:通用爬虫之CrawlSpider用法,结合实例形式分析了Scrapy框架中CrawlSpider的基本使用方法,需要的朋友可以参考下
    2020-04-04
  • Python中numpy数组真值判断的实现

    Python中numpy数组真值判断的实现

    在Python编程中,经常需要对数组进行真值判断,本文就来介绍一下Python中numpy数组真值判断的实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • Python标准库内置函数complex介绍

    Python标准库内置函数complex介绍

    这篇文章主要介绍了Python标准库内置函数complex介绍,本文先是讲解了complex的作用和使用注意,然后给出了使用示例,需要的朋友可以参考下
    2014-11-11
  • centos6.4下python3.6.1安装教程

    centos6.4下python3.6.1安装教程

    这篇文章主要为大家详细介绍了centos6.4下python3.6.1的安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • python解析.pyd文件的详细代码

    python解析.pyd文件的详细代码

    这篇文章介绍了python解析.pyd文件的详细代码,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考
    2021-12-12
  • 如何基于Python爬取隐秘的角落评论

    如何基于Python爬取隐秘的角落评论

    这篇文章主要介绍了如何基于Python爬取隐秘的角落评论,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • scrapy-splash简单使用详解

    scrapy-splash简单使用详解

    这篇文章主要介绍了scrapy-splash简单使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • python动态文本进度条的实例代码

    python动态文本进度条的实例代码

    这篇文章主要介绍了python动态文本进度条的实例代码,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-01-01

最新评论