欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈python之新式类

程序员文章站 2022-05-28 08:53:41
前言 本文中代码运行的python版本一律采取2.7.13 科普: 经典类:classic class 新式类:new-style class...

前言

本文中代码运行的python版本一律采取2.7.13

科普:

经典类:classic class

新式类:new-style class

  1. python2.2 之前并没有新式类
  2. python2.2-2.7 新式类与经典类并存, 默认使用经典类, 除非显式继承object
  3. python3.x 中去除了经典类, 用户定义的所有类都隐式继承自object

 如何使用新式类

 class new(object): # 显式继承object类
 pass

class old: 
 pass
  
class old2():
 pass 

上述代码中的3种定义类的方法, 只有第一种方法定义的是新式类.

新式类vs经典类 

新式类与经典类最主要的区别在于继承顺序, 事实上, 对于用户定义的每一个类, python 都会计算出一个方法解析顺序(method resolution order, mro)列表,它代表了类继承的顺序, 而由于经典类与新式类采用的算法不一致, 相同的继承关系可能会出现不一样的mro列表.

import inspect
class d:
  pass
 
class c(d):
  pass 
 
class b(d):
  pass
 
class a(b, c):
  pass  

print inspect.getmro(a)
# (<class __main__.a at 0x000000000322bb88>, 
# <class __main__.b at 0x000000000322b9a8>, 
# <class __main__.d at 0x000000000322bc48>, 
# <class __main__.c at 0x000000000322b948>)

class d(object):
  pass
 
class c(d):
  pass
 
class b(d):
  pass
 
class a(b, c):
  pass

print inspect.getmro(a)

# (<class '__main__.a'>, 
<class '__main__.b'>, 
<class '__main__.c'>, 
<class '__main__.d'>, 
<type 'object'>) 

可以看到, 经典类的mro顺序a-b-d-c 与新式类的mro顺序 a-b-c-d-object 是存在差异的, 这可能会是我们日常会遇到的坑.

而除了继承顺序的差异, 新式类还添加了内置属性__slots__

一般来说, 每个实例都有一个字典来管理实例的属性, 我们可以用__dict__ 来查看(__dict__并不保存类属性),它允许我们动态地修改实例的属性, 但是这也意味着每个实例都会有1个独立的字典需要我们去维护, 当我们需要创建大量的实例时, 这个操作是十分消耗内存的.

当我们在定义类时添加了__slots__属性后, 对象在实例化时就不会创建字典来管理实例属性, 而实例只能定义在__slots__里边已经设定好的属性名, 不允许动态添加其他未在__slots__里定义的属性

 class student(object):
 __slots__ = ('id', 'name', 'gender')
 def exam(self):
  pass

s1 = student()
'__dict__' in dir(s1) # false
s1.id = 10001
s1.class = 1 
# attributeerror: 'student' object has no attribute 'class'

def func():
 pass

s1.exam = func 
# attributeerror: 'student' object attribute 'f' is read-only

使用__slots__ 后我们不再能够动态地修改实例的属性, 那么使用__slots__究竟有什么好处呢?

优点:
 1.节省内存
 2.提高属性访问速度

缺点:
 1.不能动态修改实例属性

当然, 除了继承顺序和__slots__, 新式类添加了__getattribute__方法, 还修改了实例的类型

 class new(object):
 pass
 
class old:
 pass
 
new = new()
old = old()
print(new)
# <__main__.new object at 0x0000000003262208>
print(old)
# <__main__.old instance at 0x000000000321c6c8>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。