您现在的位置是:网站首页> 编程资料编程资料
Python中类的mro与继承关系详解(二)_python_
2023-05-26
468人已围观
简介 Python中类的mro与继承关系详解(二)_python_
前言
版本:
- 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,而Gamma跟Alpha并不是同源的,类似于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解析优先级排在最后,Beta跟Omega可以看做是Beta跟Gamma的优先级比较,因为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数字比较与类结构_python_
- Python中类的mro与继承关系详解_python_
- Python数据分析numpy数组的3种创建方式_python_
- Python实现yaml与json文件批量互转_python_
- Python pip超详细教程之pip的安装与使用_python_
- 利用Seaborn绘制20个精美的pairplot图_python_
- Python处理时间戳和时间计算等的脚本分享_python_
- Python Flask中Cookie和Session区别详解_python_
- Python使用Flask Migrate模块迁移数据库_python_
- Python制作简易版2048小游戏_python_
