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中使用pngquant压缩png图片的教程
Apr 09 Python
python开发之for循环操作实例详解
Nov 12 Python
python用装饰器自动注册Tornado路由详解
Feb 14 Python
python正则表达式及使用正则表达式的例子
Jan 22 Python
python实现简单遗传算法
Mar 19 Python
Django发送邮件功能实例详解
Sep 02 Python
解决python 读取excel时 日期变成数字并加.0的问题
Oct 08 Python
Python 、Pycharm、Anaconda三者的区别与联系、安装过程及注意事项
Oct 11 Python
解决pip install psycopg2出错问题
Jul 09 Python
Django如何实现防止XSS攻击
Oct 13 Python
编写python程序的90条建议
Apr 14 Python
Python 键盘事件详解
Nov 11 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防注入漏洞过滤函数代码
2012/04/11 PHP
php程序总是提示验证码输入有误解决方案
2015/01/07 PHP
[原创]php实现 data url的图片生成与保存
2016/12/04 PHP
老生常谈文本文件和二进制文件的区别
2017/02/27 PHP
浅谈PHP接入(第三方登录)QQ登录 OAuth2.0 过程中遇到的坑
2017/10/13 PHP
jquery scroll()区分横向纵向滚动条的方法
2014/04/04 Javascript
node.js中的events.emitter.removeListener方法使用说明
2014/12/10 Javascript
js超时调用setTimeout和间歇调用setInterval实例分析
2015/01/28 Javascript
JavaScript自定义等待wait函数实例分析
2015/03/23 Javascript
JS实现仿腾讯微博无刷新删除微博效果代码
2015/10/16 Javascript
JS实现页面载入时随机显示图片效果
2016/09/07 Javascript
js中动态创建json,动态为json添加属性、属性值的实例
2016/12/02 Javascript
angular仿支付宝密码框输入效果
2017/03/25 Javascript
JS继承与闭包及JS实现继承的三种方式
2017/10/15 Javascript
javascript显示动态时间的方法汇总
2018/07/06 Javascript
Vue中的$set的使用实例代码
2018/10/08 Javascript
js实现简单的贪吃蛇游戏
2020/04/23 Javascript
JS代码简洁方式之函数方法详解
2020/07/28 Javascript
[01:02:38]DOTA2-DPC中国联赛定级赛 LBZS vs Phoenix BO3第二场 1月10日
2021/03/11 DOTA
Python解惑之整数比较详解
2017/04/24 Python
Python八大常见排序算法定义、实现及时间消耗效率分析
2018/04/27 Python
windows下安装Python的XlsxWriter模块方法
2018/05/03 Python
python实现雪花飘落效果实例讲解
2019/06/18 Python
解决在pycharm运行代码,调用CMD窗口的命令运行显示乱码问题
2019/08/23 Python
Django admin禁用编辑链接和添加删除操作详解
2019/11/15 Python
django的模型类管理器——数据库操作的封装详解
2020/04/01 Python
Django REST 异常处理详解
2020/07/15 Python
详细分析Python collections工具库
2020/07/16 Python
python输出国际象棋棋盘的实例分享
2020/11/26 Python
ManoMano英国:欧洲第一家专注于DIY和园艺市场的电商平台
2020/03/12 全球购物
出纳岗位职责
2013/11/09 职场文书
2015年大学教师工作总结
2015/05/20 职场文书
OpenCV全景图像拼接的实现示例
2021/06/05 Python
java泛型通配符详解
2021/07/25 Java/Android
Netflix《海贼王》真人版剧集多张片场照曝光
2022/04/04 日漫
springboot用户数据修改的详细实现
2022/04/06 Java/Android