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 相关文章推荐
简介Django中内置的一些中间件
Jul 24 Python
利用Python自动监控网站并发送邮件告警的方法
Aug 24 Python
Python随机数random模块使用指南
Sep 09 Python
python+pillow绘制矩阵盖尔圆简单实例
Jan 16 Python
django Serializer序列化使用方法详解
Oct 16 Python
python单线程文件传输的实例(C/S)
Feb 13 Python
Python中拆分字符串的操作方法
Jul 23 Python
python笔记_将循环内容在一行输出的方法
Aug 08 Python
详解Python利用random生成一个列表内的随机数
Aug 21 Python
Python对wav文件的重采样实例
Feb 25 Python
基于Python绘制个人足迹地图
Jun 01 Python
python3实现语音转文字(语音识别)和文字转语音(语音合成)
Oct 14 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
codeigniter中测试通过的分页类示例
2014/04/17 PHP
php实现简单加入购物车功能
2017/03/07 PHP
PHP中isset、empty的用法与区别示例详解
2020/11/05 PHP
JQuery 构建客户/服务分离的链接模型中Table中的排序分析
2010/01/22 Javascript
DIV菜单层实现代码
2010/11/19 Javascript
js实现兼容IE和FF的上下层的移动
2015/05/04 Javascript
jQuery实现鼠标悬停背景翻转的黑色导航菜单代码
2015/09/14 Javascript
[原创]JQuery 在表单提交之前修改 提交的值
2016/04/14 Javascript
js常用方法、检查是否有特殊字符串、倒序截取字符串操作完整示例
2020/01/26 Javascript
js模拟实现烟花特效
2020/03/10 Javascript
使用vue编写h5公众号跳转小程序的实现代码
2020/11/27 Vue.js
[49:31]TFT vs Mski Supermajor小组赛C组 BO3 第一场 6.3
2018/06/04 DOTA
Python自动连接ssh的方法
2015/03/07 Python
python 线程的暂停, 恢复, 退出详解及实例
2016/12/06 Python
Python使用base64模块进行二进制数据编码详解
2018/01/11 Python
python画折线图的程序
2018/07/26 Python
用sqlalchemy构建Django连接池的实例
2019/08/29 Python
使用Python画出小人发射爱心的代码
2019/11/23 Python
Python2 与Python3的版本区别实例分析
2020/03/30 Python
解决keras backend 越跑越慢问题
2020/06/18 Python
Python调用C/C++的方法解析
2020/08/05 Python
CSS3实现歌词进度文字颜色填充变化动态效果的思路详解
2020/06/02 HTML / CSS
HTML5 Geolocation API的正确使用方法
2018/12/04 HTML / CSS
使用Html5中的cavas画一面国旗
2019/09/25 HTML / CSS
英国老牌潮鞋店:Offspring
2019/08/19 全球购物
周生生珠宝香港官网:Chow Sang Sang(香港及海外配送)
2019/09/05 全球购物
阿联酋最好的手机、电子产品和家用电器网上商店:Eros Digital Home
2020/08/09 全球购物
外企C语言笔试题
2013/11/10 面试题
大学生自我鉴定
2013/12/16 职场文书
读书演讲主持词
2014/03/18 职场文书
三八活动策划方案
2014/08/17 职场文书
2014年妇联工作总结
2014/11/21 职场文书
药品销售员2015年终工作总结
2015/10/22 职场文书
如何书写先进事迹材料?
2019/07/02 职场文书
厉害!这是Redis可视化工具最全的横向评测
2021/07/15 Redis
利用Matlab绘制各类特殊图形的实例代码
2021/07/16 Python