Python新式类与经典类的区别及__slots__用法解析

不晚
不晚
发布时间:2026-10-13 | 6人浏览过
原创

本文对比Python经典类与新式类的核心差异,重点解析Python2.7中默认经典类与显式继承object的新式类在MRO顺序上的不同。同时深入讲解新式类特有的__slots__机制,说明其如何通过限制属性动态添加来节省内存并提升访问速度,适用于需要优化大量实例内存占用的场景。

前言

本文所有代码示例均基于Python 2.7.13版本运行。

基础概念科普:

经典类(classic class)

新式类(new-style class)

  1. 在Python 2.2版本之前,不存在新式类的概念。
  2. 在Python 2.2至2.7版本中,经典类与新式类并存,默认情况下使用经典类,除非显式继承自object类。
  3. 在Python 3.x版本中,经典类已被移除,用户定义的所有类均隐式继承自object。

如何定义新式类

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

class Old: 
 pass
  
class Old2():
 pass 

上述代码中展示的三种类定义方式中,仅第一种方式定义的是新式类。

新式类与经典类的对比

新式类与经典类最显著的区别在于继承顺序。实际上,对于用户定义的每一个类,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__不保存类属性)。这允许我们动态修改实例的属性,但也意味着每个实例都需要维护一个独立的字典,当需要创建大量实例时,这种操作会消耗大量内存。

当在定义类时添加了__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>

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

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表