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

作者:??宿者朽命??? 时间:2022-02-28 07:34:17 

前言

版本:

  • 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

来源:https://juejin.cn/post/7124991737952632839

标签:Python,类,mro,继承,关系
0
投稿

猜你喜欢

  • asp 过滤非法字符函数

    2011-04-07 10:39:00
  • 带你深入了解SQL Server 2008的独到之处

    2009-01-07 14:20:00
  • 数据库连接字符串的常见问题和解决方法

    2008-11-28 15:16:00
  • 编写和优化SQL Server的存储过程

    2009-04-13 10:13:00
  • 安装并免费使用Pycharm专业版(学生/教师)

    2023-09-27 08:14:13
  • Python函数实现学员管理系统

    2023-06-22 03:32:30
  • python3发送邮件需要经过代理服务器的示例代码

    2023-07-27 01:00:44
  • Python实战之实现康威生命游戏

    2022-06-30 14:21:12
  • Go项目配置管理神器之viper的介绍与使用详解

    2023-09-17 01:05:52
  • 网页iframe元素应用浅析

    2009-04-11 18:11:00
  • 一个简单的python程序实例(通讯录)

    2023-05-16 06:49:11
  • 将 Ubuntu 16 和 18 上的 python 升级到最新 python3.8 的方法教程

    2022-12-16 07:50:17
  • SQL Server 2005中数据库镜像的四个问题

    2009-02-19 16:48:00
  • Python FTP文件定时自动下载实现过程解析

    2023-04-30 19:08:51
  • Python中getservbyport和getservbyname函数的用法大全

    2023-04-14 09:02:38
  • Django零基础入门之模板变量详解

    2023-03-19 11:17:16
  • [原创][分享]数字格式化转换

    2011-07-04 12:20:15
  • PHP结构型模式之外观模式

    2023-05-25 11:43:14
  • PHP PDOStatement::fetch讲解

    2023-06-04 20:06:02
  • pytorch教程网络和损失函数的可视化代码示例

    2023-11-26 16:13:51
  • asp之家 网络编程 m.aspxhome.com