Python slots 详解(上篇)
在 Python 中,每个对象都附带着一些额外的信息,比如类型信息、引用计数等等,这些信息会占用一些内存空间。开发者可以通过 __dict__
属性存储对象的动态属性,但这会导致额外的内存占用,尤其是对于大量实例化的对象。针对这个问题,Python 提供了 __slots__
这个属性,可以让开发者手动定义对象的属性,减少内存空间的占用。
slots 的使用
__slots__
是一个包含了字符串属性名称的元组,用来限制实例的属性。在类中使用 __slots__
的示例如下:
class MyClass:
__slots__ = ('x', 'y', 'z')
def __init__(self, x=0, y=0, z=0):
self.x = x
self.y = y
self.z = z
这里我们定义一个 MyClass
类,使用 __slots__
属性让实例的属性只能是 x
、y
、z
中的一个。使用 __slots__
不仅可以减少内存占用,还能够防止属性名称的拼写错误,提高代码的可读性和可维护性。当试图访问不存在的属性时,Python 会抛出 AttributeError
异常。
slots 的实现
使用 __slots__
机制,Python 将实例变量存储在一个 tuple 类型的数据结构中,而不是像普通的对象一样存储在字典中。这意味着我们无法像使用字典那样通过对象实例的 __dict__
属性来查看对象的属性字典,从而减少了内存占用。
下面是 __dict__
和 __slots__
模式下对象的内存占用的比较:
Normal object __slots__ object
Type object pointer: 16 bytes Type object pointer: 16 bytes
Reference count: 28 bytes Reference count: 28 bytes
__dict__: 48 bytes __slots__ data: 24 bytes
Padding: 8 bytes Padding: 20 bytes
Total: 100 bytes Total: 88 bytes
可以看到,使用 __slots__
模式下,相比普通对象内存占用可以减少一些,因为不需要额外存储一个 __dict__
属性。不过需要注意的是,由于使用了元组存储对象属性,因此当对象需要动态添加属性时,就需要重新创建一个新的元组,这也会导致一些额外的开销。
slots 的使用限制
使用 __slots__
机制需要注意以下几点:
__slots__
中的属性名称必须为字符串;- 子类中的
__slots__
会覆盖父类中的__slots__
,如果子类中需要保留父类的__slots__
,则需要在子类中显式指定; __slots__
中的属性一旦定义,就无法添加或修改,只能访问和删除;__weakref__
和__dict__
是特殊的属性,即使在__slots__
中指定了也不会起作用。
结语
本文介绍了 Python 中 __slots__
的使用方法、实现方式以及使用时需要注意的限制。在需要大量创建实例对象的场景中,使用 __slots__
功能可以有效减少内存的占用,提高代码的可读性和可维护性。但是需要注意在使用的过程中要避免一些限制和约束。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python __slots__ 详解(上篇) - Python技术站