当我们在需要创建很多实例的情况下,怎么更好的节省内存是个问题。比如一个系统,有许多用户的信息,同时访问的话会创建很多实例。
引入__slots__属性,是个很好的解决方法。如下例所示:
class First():
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Second():
__slots__ = ['name', 'age', 'gender']
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
将其实例化并看两者的属性差异:
first = First('Rose', 32, 'female')
second = Second('Jack', 30, 'male')
set(dir(first)) - set(dir(second))
输出:{'__dict__', '__weakref__'}
可以看到first比second多了这两个属性。其中'__weakref__'一般占用很少。主要说说__dict__。其中__dict__是可以动态绑定属性的:
print(first.__dict__)
输出:{'name': 'Rose', 'age': 32, 'gender': 'female'}
也就是class中定义的属性,我们在定义之后仍然可以绑定属性:
first.x = "something"
# 或者
# first.__dict__["x"] = "something"
first.__dict__
输出:{'name': 'Rose', 'age': 32, 'gender': 'female', 'x': 'something'}
删除这个属性:
del first.__dict__['x']
这样的动态绑定会占用内存,用sys模块看一下:
import sys
print(sys.getsizeof(first.__dict__))
print(sys.getsizeof(first.name))
输出:112, 53
这个字典仍然占用112个字节。在实例多的话仍然是个不小的负担。用__slots__ 限制绑定是个有效的方法。
需要注意的是,这样继承的子类仍然没有限制绑定:
class ChildSecond(Second):
pass
child = ChildSecond('Jack', 30, 'male')
child.y = 'any'
这样仍然可以绑定新的属性,除非在子类中也定义__slots__。