Python新式类与经典类的区别
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”实例类型。
更详细的:http://www.cnblogs.com/blackmatrix/p/5594109.html
大概就想到这几点,其他的有想到再补充。
Python新式类与经典类的区别的更多相关文章
- Python新式类和经典类的区别
@Python新式类和经典类的区别 class ClassicClass(): pass class NewStyleClass(object): pass x1 = ClassicClass() x ...
- python中新式类和经典类的区别
1).python在类中的定义在py2-3版本上是使用的有新式类和经典类两种情况,在新式类和经典类的定义中最主要的区别是在定义类的时候是否出现引用object;如:经典类:Class 类名::而新式类 ...
- python单例模式控制成只初始化一次,常规型的python单例模式在新式类和经典类中的区别。
单例模式的写法非常多,但常规型的单例模式就是这样写的,各种代码可能略有差异,但核心就是要搞清楚类属性 实例属性,就很容易写出来,原理完全一模一样. 如下: 源码: class A(object): d ...
- python之继承、抽象类、新式类和经典类
一.上节补充1.静态属性静态属性 : 类的属性,所有的对象共享这个变量 如果用对象名去修改类的静态属性:在对象的空间中又创建了一个属性,而不能修改类中属性的值 操作静态属性应该用类名来操作 例1:请你 ...
- python中的__new__与__init__,新式类和经典类(2.x)
在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...
- 03-python的新式类和经典类区别
新式类就是 class person(object): 这种形式的, 从py2.2 开始出现的 新式类添加了: __name__ is the attribute's name. __doc__ i ...
- python中新式类和经典类
python中的类分为新式类和经典类,具体有什么区别呢?简单的说, 1.新式类都从object继承,经典类不需要. Python 2.x中默认都是经典类,只有显式继承了object才是新式类 Pyth ...
- Python之面向对象新式类和经典类
Python之面向对象新式类和经典类 新式类和经典类的继承原理: 在Python3中,就只有新式类一种了. 先看Python3中新式类: 类是有继承顺序的: Python的类是可以继承多个类的,也就是 ...
- Python 新式类与经典类
新式类,经典类 查询匹配 广度查询 横着对每个类进行查询 深度查询 无视平级类,直接寻找下级类 #python 3.0 #新式类 广度查询 #经典类 广度查询 #python 2.0 #新式类 广度查 ...
随机推荐
- Spring Cloud 前后端分离后引起的跨域访问解决方案
背景 Spring Cloud 微服务试点改造,目前在尝试前后端分离. 前台A应用(本机8080端口),通过网管(本机8769端口)调用后台应用B(本机8082端口).应用C发布的http服务.. A ...
- ubuntu16.04 Qt5.8 如何使用opecv3.2
关于opencv3.2的编译有一大堆教程.可自寻查看.在Qt中使用opencv需要在pro文件中添加 相应的头文件和 动态链接库.如下 INCLUDEPATH += . INCLUDEPATH += ...
- iScroll的简单使用
今天是2017-1-18,每天进步一点点 今天主要来总结一下我在项目中遇到的关于iScroll的使用问题. 第一个是iscroll的初始化问题. --在页面资源(包括图片)加载完毕后100ms之后初始 ...
- 树莓派学习笔记——USB wifi配置指南
0 前言 树莓派既能够使用有线网络又能够无线网络,假设使用有线网络不方便的话能够借助USB wifi无线网卡让树莓派也插上无线"翅膀". 可是和使用有线网络即插即用的方式不 ...
- Git 经常使用命令总结
一 关于加入.删除和回退 1 git rm --cached file 想要git不再跟踪这个文件,可是又不想在硬盘中删除该文件 2 在被git管理的文件夹中删除文件时,能够选择例如以下两种方式: ...
- 25个增强iOS应用程序性能的提示和技巧(0基础篇)
在开发iOS应用程序时,让程序具有良好的性能是非常关键的. 这也是用户所期望的,假设你的程序执行迟钝或缓慢,会招致用户的差评.然而因为iOS设备的局限性,有时候要想获得良好的性能,是非常困难的. 在开 ...
- jquery通过数值改变球大小
在业务中遇到一个问题:在页面上显示一个球.且球的大小会应数字的大小而改变. 我们都知道 js是能够画圆(用css样式准备一个圆.假设addClass),但这并非我们想要的. 于是笔者脑洞打开:用样式画 ...
- 本地代码上传到GitHub---拷贝github代码
来这里: 转载请标明出处: http://blog.csdn.net/hanhailong726188/article/details/46738929 步骤: git init git add na ...
- 6.python内置函数
1. abs() 获取绝对值 >>> abs(-10) 10 >>> a = -10 >>> a.__abs__() 10 2. all() ...
- 使用angularjs实现注册表单
本文是在学习angularjs过程中做的相应的练习 github地址 https://github.com/2016Messi/angularjs1.6-form 演示地址 https://2016m ...