Python中新式类与经典类的区别详析


Posted in Python onJuly 10, 2019

1.新式类与经典类

在Python 2及以前的版本中,由任意内置类型派生出的类(只要一个内置类型位于类树的某个位置),都属于“新式类”,都会获得所有“新式类”的特性;反之,即不由任意内置类型派生出的类,则称之为“经典类”。

“新式类”和“经典类”的区分在Python 3之后就已经不存在,在Python 3.x之后的版本,因为所有的类都派生自内置类型object(即使没有显示的继承object类型),即所有的类都是“新式类”。

官方文档 https://www.python.org/doc/newstyle/

2.继承顺序的区别

主要是在多重继承时才会遇到这个问题。

经典类的钻石继承是深度优先,即从下往上搜索;新式类的继承顺序是采用C3算法(非广度优先)。

对经典类进行代码验证(所有经典类的代码必须在Python2下运行,下同),ClassicClassB 继承自 ClassicClassA,SubClassicClass继承自ClassicClassB,ClassicClassC:

class ClassicClassA():
 var = 'Classic Class A'


class ClassicClassB(ClassicClassA):
 pass


class ClassicClassC():
 var = 'Classic Class C'


class SubClassicClass(ClassicClassB, ClassicClassC):
 pass


if __name__ == '__main__':
 print(SubClassicClass.var)

在SubClassicClass对var属性进行搜索的过程中,根据从下到上的原则,会优先搜索ClassicClassB,而ClassicClassB没有var属性,会继续往上搜索ClassicClassB的超类ClassicClassA,在ClassicClassA中发现var属性后停止搜索,var的值为ClassicClassA中var的值;而ClassicClassC的var属性从始至终都未被搜索到。

从运行结果可以看出,输出的是Classic Class A,可见类继承的搜索是深度优先,由下至上进行搜索。

Classic Class A 

新式类的继承顺序并非是广度优先,而是C3算法,只是在部分情况下,C3算法的结果恰巧与广度优先的结果相同。

对新式类的继承搜索顺序进行代码验证,新式类中,可以使用mro函数来查看类的搜索顺序(这也算是一个区别),如SubNewStyleClass.mro()。

class NewStyleClassA(object):
 var = 'New Style Class A'


class NewStyleClassB(NewStyleClassA):
 pass


class NewStyleClassC(NewStyleClassA):
 var = 'New Style Class C'


class SubNewStyleClass(NewStyleClassB, NewStyleClassC):
 pass


if __name__ == '__main__':
 print(SubNewStyleClass.mro())
 print(SubNewStyleClass.var)

从代码运行结果看,恰巧与从左至右的广度优先预期结果相同。

[<class '__main__.SubNewStyleClass'>, <class '__main__.NewStyleClassB'>, <class '__main__.NewStyleClassC'>, <class '__main__.NewStyleClassA'>, <type 'object'>]
New Style Class C

但是不代表新式类的继承顺序就是广度优先,可以稍微修改下代码进行验证:NewStyleClassC改为继承自object

class NewStyleClassA(object):
 var = 'New Style Class A'


class NewStyleClassB(NewStyleClassA):
 pass


class NewStyleClassC(object):
 var = 'New Style Class C'


class SubNewStyleClass(NewStyleClassB, NewStyleClassC):
 pass


if __name__ == '__main__':
 print(SubNewStyleClass.mro())
 print(SubNewStyleClass.var)

运行结果不再符合广度优先:

[<class '__main__.SubNewStyleClass'>, <class '__main__.NewStyleClassB'>, <class '__main__.NewStyleClassA'>, <class '__main__.NewStyleClassC'>, <type 'object'>]
New Style Class A

可见,新式类的继承顺序并非广度优先,而是C3算法。至于C3算法,以后再另外详细写。

3.类实例类型的区别

在经典类中,所有的类都是classobj类型,而类的实例都是instance类型。类与实例只有通过__class__属性进行关联。这样在判断实例类型时,就会造成不便:所有的实例都是instance类型。

class A():pass
class B():pass

a = A()
b = B()

if __name__ == '__main__':
 print(type(a))
 print(type(b))
 print(type(a) == type(b))

type(a) == type(b)的结果永远为True,那这样的比较就毫无意义。

更为麻烦的是,经典类的实例是instance类型,而内置类的实例却不是,无法统一。

通过代码判断下内置类型list的实例[1, 2, 3]是什么类型

print(type([1, 2, 3]))

运行结果,是list类型

<type 'list'>

内置类的实例类型和经典类的实例类型完全不同,容易造成困惑,不利于代码的统一。

这个问题在Python 3之后就不复存在了,因为Python3中所有的类都是新式类,新式类中类与类型已经统一:类实例的类型是这个实例所创建自的类(通常是和类实例的__class__相同),而不再是Python 2.x版本中的“instance”实例类型。

更详细的:https://3water.com/article/165048.htm

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python实现保存网页到本地示例
Mar 16 Python
wxpython中自定义事件的实现与使用方法分析
Jul 21 Python
python实现将一个数组逆序输出的方法
Jun 25 Python
Python设计模式之观察者模式原理与用法详解
Jan 16 Python
python 利用pandas将arff文件转csv文件的方法
Feb 12 Python
Python中的正则表达式与JSON数据交换格式
Jul 03 Python
Python assert语句的简单使用示例
Jul 28 Python
Python中调用其他程序的方式详解
Aug 06 Python
python 实现二维字典的键值合并等函数
Dec 06 Python
python内打印变量之%和f的实例
Feb 19 Python
Python GUI编程学习笔记之tkinter界面布局显示详解
Mar 30 Python
python3.7调试的实例方法
Jul 21 Python
详解Pandas之容易让人混淆的行选择和列选择
Jul 10 #Python
python的几种矩阵相乘的公式详解
Jul 10 #Python
Python内存管理实例分析
Jul 10 #Python
OpenCV 边缘检测
Jul 10 #Python
python使用Qt界面以及逻辑实现方法
Jul 10 #Python
用Python实现BP神经网络(附代码)
Jul 10 #Python
OpenCV 模板匹配
Jul 10 #Python
You might like
PHP新手上路(四)
2006/10/09 PHP
ThinkPHP实现批量删除数据的代码实例
2014/07/02 PHP
centos+php+coreseek+sphinx+mysql之一coreseek安装篇
2016/10/25 PHP
简单通用的JS滑动门代码
2008/12/19 Javascript
jQuery中的bind绑定事件与文本框改变事件的临时解决方法
2010/08/13 Javascript
自用js开发框架小成 学习js的朋友可以看看
2010/11/16 Javascript
原生javascript获取元素样式属性值的方法
2010/12/25 Javascript
javascript 原型继承介绍
2011/08/30 Javascript
yepnope.js 异步加载资源文件
2011/09/08 Javascript
javascript 禁用IE工具栏,导航栏等等实现代码
2013/04/01 Javascript
原生javascript模仿win8等待提示圆圈进度条
2014/04/24 Javascript
解决Jstree 选中父节点时被禁用的子节点也会选中的问题
2017/12/27 Javascript
js保留两位小数方法总结
2018/01/31 Javascript
JS设计模式之策略模式概念与用法分析
2018/02/05 Javascript
vue2.0 自定义 饼状图 (Echarts)组件的方法
2018/03/02 Javascript
react配合antd组件实现的管理系统示例代码
2018/04/24 Javascript
[jQuery] 事件和动画详解
2019/03/05 jQuery
JS实现判断数组是否包含某个元素示例
2019/05/24 Javascript
JS面向对象编程基础篇(一) 对象和构造函数实例详解
2020/03/03 Javascript
[15:58]DOTA2国际邀请赛采访专栏:Tongfu.Sansheng&KingJ,DK.rOtk
2013/08/08 DOTA
[01:48]2018DOTA2亚洲邀请赛主赛事第二日五佳镜头 VG完美团战逆转TNC
2018/04/05 DOTA
解决pyqt中ui编译成窗体.py中文乱码的问题
2016/12/23 Python
Python自定义线程池实现方法分析
2018/02/07 Python
python批量导入数据进Elasticsearch的实例
2018/05/30 Python
使用python对文件中的数值进行累加的实例
2018/11/28 Python
pyqt5 实现 下拉菜单 + 打开文件的示例代码
2019/06/20 Python
Python实现图片添加文字
2019/11/26 Python
Pycharm修改python路径过程图解
2020/05/22 Python
浅析python 通⽤爬⾍和聚焦爬⾍
2020/09/28 Python
NIHAOMARKET官方海外旗舰店:意大利你好华人超市
2018/01/27 全球购物
预备党员党校学习自我评价分享
2013/11/12 职场文书
表彰会主持词
2014/03/26 职场文书
平安工地汇报材料
2014/08/19 职场文书
社区综治工作汇报
2014/10/27 职场文书
运动会1000米加油稿
2015/07/21 职场文书
opencv深入浅出了解机器学习和深度学习
2022/03/17 Python