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操作MySQL模拟银行转账
Mar 12 Python
Python+request+unittest实现接口测试框架集成实例
Mar 16 Python
PyQt5每天必学之QSplitter实现窗口分隔
Apr 19 Python
django中静态文件配置static的方法
May 20 Python
PyCharm代码提示忽略大小写设置方法
Oct 28 Python
python中for循环输出列表索引与对应的值方法
Nov 07 Python
在python中实现对list求和及求积
Nov 14 Python
详解Python中打乱列表顺序random.shuffle()的使用方法
Nov 11 Python
Python模块的定义,模块的导入,__name__用法实例分析
Jan 07 Python
Jupyter Notebook远程登录及密码设置操作
Apr 10 Python
python如何运行js语句
Sep 09 Python
深入理解python协程
Jun 15 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 输出双引号&quot;与单引号'的方法
2010/05/09 PHP
php中XMLHttpRequest(Ajax)不能设置自定义的Referer的解决方法
2011/11/26 PHP
JavaScript面向对象之体会[总结]
2008/11/13 Javascript
jQuery ctrl+Enter shift+Enter实现代码
2010/02/07 Javascript
通过继承IHttpHandle实现JS插件的组织与管理
2010/07/13 Javascript
鼠标经过tr时,改变tr当前背景颜色
2014/01/13 Javascript
浅谈javascript属性onresize
2015/04/20 Javascript
JQuery中属性过滤选择器用法实例分析
2015/05/18 Javascript
Nodejs爬虫进阶教程之异步并发控制
2016/02/15 NodeJs
JavaScript模拟push
2016/03/06 Javascript
JS数字千分位格式化实现方法总结
2016/12/16 Javascript
详解js前端代码异常监控
2017/01/11 Javascript
js实现分页功能
2017/05/24 Javascript
vue使用Axios做ajax请求详解
2017/06/07 Javascript
vue项目实现记住密码到cookie功能示例(附源码)
2018/01/31 Javascript
利用angular、react和vue实现相同的面试题组件
2018/02/19 Javascript
vue-cli项目代理proxyTable配置exclude的方法
2018/09/20 Javascript
JS动态显示倒计时效果
2019/12/12 Javascript
[03:07]2015国际邀请赛选手档案EHOME.rOtK 是什么让他落泪?
2015/07/31 DOTA
[47:21]Liquid vs TNC Supermajor 胜者组 BO3 第一场 6.4
2018/06/05 DOTA
Python对象体系深入分析
2014/10/28 Python
Python中的两个内置模块介绍
2015/04/05 Python
对python中Librosa的mfcc步骤详解
2019/01/09 Python
在Python 不同级目录之间模块的调用方法
2019/01/19 Python
PYTHON发送邮件YAGMAIL的简单实现解析
2019/10/28 Python
python3.7.3版本和django2.2.3版本是否可以兼容
2020/09/01 Python
python 星号(*)的多种用途
2020/09/21 Python
如何在Anaconda中打开python自带idle
2020/09/21 Python
python实现计算器简易版
2020/12/17 Python
自荐书格式
2013/12/01 职场文书
2014第二批党员干部对照“四风”找差距检查材料思想汇报
2014/09/18 职场文书
推荐六本经典文学奖书籍:此生必读
2019/08/22 职场文书
导游词范文之颐和园/重庆/云台山
2019/09/10 职场文书
《没有任何借口》读后感:完美的执行能力
2020/01/07 职场文书
总结一些Java常用的加密算法
2021/06/11 Java/Android
MySQL深分页问题解决思路
2022/12/24 MySQL