首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

python进阶系列(二)-多继承与super

每天读一篇一线开发者原创好文

上一篇我们介绍了python中装饰器的实现原理与工作方式,并且对python中的对象、闭包等概念有简单的描述,后继还会对装饰器做进一步的阐述。

本篇我带大家来了解一个高级语言、尤其是面向对象语言中老生常谈的概念:继承。

谈到面向对象,大家都知道三个基本特征:继承、封装和多态。其中的继承是指语言具备这样一种能力:对于现有类的所有功能无需重新编写,就可以对这些类进行扩展,从而实现一个新的派生类。相信大家在入门python的过程中,一定已经接触或者使用过继承来实现一个新的类,但是对于python中继承的实现、特点以及同其他高级语言的区别可能还没有一个深层次的认知,下面我从初学者的角度来简单介绍python的继承概念。

1.单继承

这部分其实是属于python基础知识,为了循序渐进,这里简单介绍一下。

从这个简单的例子中我们看出,python对子类方法的两种实现:改写和新增。在我们得到一个子类的实例时,这个实例和原先的父类还有关系吗?python内置的方法isinstance()可以判断某个实例(对象)是否属于某个类,我们再看下面这个示例。

从这个例子可以看出,一个子类的实例也是它父类的实例对象。通过这个特点我们可以来判断某些实例对象他们的类是否拥有同样的父类甚至祖先类。

2.多继承

如果你在实现某个新的类时想让它同时继承多个父类,python也是天然支持的,这就是多继承。

类D继承了类B和类C,最终代码输出 “in A”,这其实比较好理解,实例d在查找方法showSomeThing时发现类D没有,于是去第一个父类B中查找,发现也没有,就去B的父类A中查找,最终找到了。但是大家可能有个疑问,为何在父类B中找不到方法时,不去另一个父类C中查找方法呢?我们再来看这样一个例子。

这次输出变成了“in C”!我猜部分读者甚至都没有发现两块代码的区别,提醒大家注意一下,在父类A中,他继承了超类object,导致最终结果的不同。这其实是python版本更迭带来的变化,从2.2版本开始,python引入了新式类的概念(new style class),将一切继承自超类object的class称为新式类,不从object继承的类(包括所有的父类也未从object继承过)称为旧类(也叫经典类)。

python的旧类在多继承时采用深度优先遍历父类,新类则采用的是广度优先遍历(更准确来讲是C3算法,这里不再详细展开),这就是为何上面两个例子输出不同的原因。由于新类的高度统一的特性,现在强烈建议大家在代码中使用新式类。

3.super

我们平时继承一个类并且扩展某一个方法时,都是使用super()来调用他的父类方法的。这一小节,主要是强调一个概念:不要一提到super就想到父类,他们其实并不等价!

python官方文档中是这么介绍super()方法的:super() 函数用于调用下一个父类(超类)并返回该父类实例的方法。我们在单继承或者单层继承时,可能都不用考虑,直接用super()来调用父类的方法,但是super()实际上是如何调用的呢?定义里的“下一个父类”又是指什么呢?来看这个例子。

看看最终的输出,是不是和你的预期不一致呢?这其实是python引入新类后,为了解决多继承、菱形继承(钻石继承)采取的一种手段,引入了MRO的概念。请注意,只有新类才能使用super()方法。

MRO(method resolution order),即方法解释顺序,主要用来在类多继承时判断类方法的路径,来帮助super寻找“下一个父类”。python中类自带属性mro,可以打印出类的继承路径。

类的属性__mro__或者方法mro()都能打印出类的继承顺序,super()在执行时查找这个列表,到列表当前位置的类中去查找他的下一个类。我们看刚刚这个例子,在执行完“in B”之后执行super(),查找mro,看到类B的下一个类是C,因此开始执行C的__init()__方法,所以输出“in C”。此后super()再次查找mro,发现C之后是父类A,因此执行A的__init()__方法,最终输出的结果就能理解了。

再次强调,不要一提到super就想到父类,他实际是根据mro来查找下一个类的。

4.小结

本篇主要是介绍了python中的多继承和super的工作机制,将大家平时会忽视的super执行顺序理了一遍。其实前面提到的几个例子都是存在菱形继承的问题,在实际使用中应当尽量避免。另外上面提到的python新旧类的问题,在python3中已经不存在了,所有的类默认都是继承自object超类,即所有的类都是新式类。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180205B0V0OU00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券