从Python2.2开始,Python引入了 new style class(新式类)

新式类跟经典类的差别主要是以下几点:


  1. 新式类对象可以直接通过__class__属性获取自身类型:type

[python]view plaincopy
  1. #-*-coding:utf-8-*-
  2. classE:
  3. #经典类
  4. pass
  5. classE1(object):
  6. #新式类
  7. pass
  8. e=E()
  9. print"经典类"
  10. printe
  11. printtype(e)
  12. printe.__class__
  13. print"新式类"
  14. e1=E1()
  15. printe1
  16. printe1.__class__
  17. printtype(e1)
[python]view plaincopy
  1. 经典类
  2. <__main__.Einstanceat0x0000000002250B08>
  3. <type'instance'>
  4. __main__.E
  5. 新式类
  6. <__main__.E1objectat0x0000000002248710>
  7. <class'__main__.E1'>
  8. <class'__main__.E1'>

我使用的是python2.7。

E1是定义的新式类。那么输输出e1的时候,不论是type(e1),还是e1.__class__都是输出的<class '__main__.E1'>。


2. 继承搜索的顺序发生了改变,经典类多继承属性搜索顺序: 先深入继承树左侧,再返回,开始找右侧;新式类多继承属性搜索顺序: 先水平搜索,然后再向上移动

[python]view plaincopy
  1. #-*-coding:utf-8-*-
  2. classA(object):
  3. """
  4. 新式类
  5. 作为所有类的基类
  6. """
  7. deffoo(self):
  8. print"classA"
  9. classA1():
  10. """
  11. 经典类
  12. 作为所有类的基类
  13. """
  14. deffoo(self):
  15. print"classA1"
  16. classC(A):
  17. pass
  18. classC1(A1):
  19. pass
  20. classD(A):
  21. deffoo(self):
  22. print"classD"
  23. classD1(A1):
  24. deffoo(self):
  25. print"classD1"
  26. classE(C,D):
  27. pass
  28. classE1(C1,D1):
  29. pass
  30. e=E()
  31. e.foo()
  32. e1=E1()
  33. e1.foo()


输出

[python]view plaincopy
  1. classD
  2. classA1


因为A新式类,对于继承A类都是新式类,首先要查找类E中是否有foo(),如果没有则按顺序查找C->D->A。它是一种广度优先查找方式。

因为A1经典类,对于继承A1类都是经典类,首先要查找类E1中是否有foo(),如果没有则按顺序查找C1->A1->D1。它是一种深度优先查找方式。


3. 新式类增加了__slots__内置属性, 可以把实例属性的种类锁定到__slots__规定的范围之中。


比如只允许对A实例添加name和age属性:

[python]view plaincopy
  1. #-*-coding:utf-8-*-
  2. classA(object):
  3. __slots__=('name','age')
  4. classA1():
  5. __slots__=('name','age')
  6. a1=A1()
  7. a=A()
  8. a1.name1="a1"
  9. a.name1="a"


A是新式类添加了__slots__ 属性,所以只允许添加name age

A1经典类__slots__ 属性没用,

[python]view plaincopy
  1. Traceback(mostrecentcalllast):
  2. File"t.py",line13,in<module>
  3. a.name1="a"
  4. AttributeError:'A'objecthasnoattribute'name1'

所以a.name是会出错的



通常每一个实例都会有一个__dict__属性,用来记录实例中所有的属性和方法,也是通过这个字典,可以让实例绑定任意的属性

而__slots__属性作用就是,当类C有比较少的变量,而且拥有__slots__属性时,

类C的实例 就没有__dict__属性,而是把变量的值存在一个固定的地方。如果试图访问一个__slots__中没有

的属性,实例就会报错。这样操作有什么好处呢?__slots__属性虽然令实例失去了绑定任意属性的便利,

但是因为每一个实例没有__dict__属性,却能有效节省每一个实例的内存消耗,有利于生成小而精

干的实例。


4. 新式类增加了__getattribute__方法

[python]view plaincopy
  1. classA(object):
  2. def__getattribute__(self,*args,**kwargs):
  3. print"A.__getattribute__"
  4. classA1():
  5. def__getattribute__(self,*args,**kwargs):
  6. print"A1.__getattribute__"
  7. a1=A1()
  8. a=A()
  9. a.test
  10. print"========="
  11. a1.test
[python]view plaincopy
  1. A.__getattribute__
  2. =========
  3. Traceback(mostrecentcalllast):
  4. File"t.py",line18,in<module>
  5. a1.test
  6. AttributeError:A1instancehasnoattribute'test'

可以看出A是新式类,每次通过实例访问属性,都会经过__getattribute__函数,

A1不会调用__getattribute__所以出错了



Python 2.x中默认都是经典类,只有显式继承了object才是新式类

Python 3.x中默认都是新式类,不必显式的继承object

更多相关文章

  1. Python数据挖掘实例(实时更新)
  2. AttributeError:“MatrixFactorizationModel”对象没有属性“sav
  3. Python------类的结构细分,异常处理,方法,属性
  4. Python进阶----类的结构(公有成员 , 私有成员(私有属性,私有方法
  5. AttributeError:'Flask'对象没有属性'login_manager' - Login_Ma
  6. 关于Python的属性、参数、方法的解释、区别
  7. 使用Python编写简单的端口扫描器的实例分享【转】
  8. python函数的属性
  9. UNIX-LINUX编程实践教程->第八章->实例代码注解->写一个简单的sh

随机推荐

  1. android 重力感应初步认识
  2. Android调用输入法软键盘,返回输入的内容
  3. android中使用afinal一行代码显示网络图
  4. Android文件系统保护——dmverity
  5. Camera Flash的获得权限
  6. 2.5.3 使用alertDialog创建自定义对话框
  7. Android 已发行多年,移动 App 已经趋近饱
  8. Fetching https://dl-ssl.google.com/and
  9. 登录案例_android
  10. Android统计图集合源码