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

作者:BlackMatrix 时间:2022-02-04 05:11:16 

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://www.jb51.net/article/165048.htm

来源:https://www.cnblogs.com/blackmatrix/p/5630515.html

标签:python,新式类,经典类
0
投稿

猜你喜欢

  • 谈点关于checkbox的事情

    2010-09-28 14:49:00
  • python检测远程端口是否打开的方法

    2022-01-28 01:45:19
  • python tornado使用流生成图片的例子

    2023-08-24 07:07:20
  • 使用SQL Server 2000索引视图提高性能

    2009-01-13 13:47:00
  • Jmeter并发执行Python 脚本的完整流程

    2021-05-12 02:52:49
  • 导航与搜索合并的可能性

    2009-09-27 12:06:00
  • Golang 内存管理简单技巧详解

    2023-06-24 22:38:18
  • python使用BeautifulSoup分析网页信息的方法

    2022-02-07 11:33:40
  • python 绘图模块matplotlib的使用简介

    2023-08-09 19:09:01
  • 酷! 程序员用Python带你玩转冲顶大会

    2022-02-20 11:56:08
  • 详解Django将秒转换为xx天xx时xx分

    2023-06-14 22:52:12
  • Python实现截图生成符合markdown的链接

    2021-07-09 10:18:22
  • 巧用Dreamweaver MX制作阴影字

    2009-08-31 17:36:00
  • tensorflow mnist 数据加载实现并画图效果

    2023-10-20 15:07:33
  • 基于python框架Scrapy爬取自己的博客内容过程详解

    2021-12-21 06:39:30
  • python logging模块的使用总结

    2021-11-15 06:46:53
  • 如何列出我所需要数据视图?

    2010-01-12 20:00:00
  • python通过wxPython打开一个音频文件并播放的方法

    2021-10-20 16:15:08
  • Python3 读取Word文件方式

    2021-03-21 22:36:37
  • mysql与sqlserver的所有区别

    2009-02-27 16:18:00
  • asp之家 网络编程 m.aspxhome.com