python版本:3.6
1、__slots__的作用
一般情况下,Python允许在程序运行时给对象绑定新的属性或方法。但是,如果我们要限定自定义类型的对象只能绑定某些属性,可以通过在类中定义__slots__变量来进行限定,这相当于告诉解释器,实例的属性都叫什么,并且只能有这些属性,在定义时,推荐__slots__使用元组,而不是列表,这样做可以节省内存,__slots__的限定只对当前类的对象生效,对子类并不起任何作用。
2、实例:
本文章仅供学习做记录,如有侵权,告知删除。
本例中使用了__slots__,__dict__,内存统计方法的使用。关于__dict__方法的使用,在下一篇介绍。
import sys
import tracemalloc
class Person1(object):
def __init__(self, pid, name, age):
self.pid = pid
self.name = name
self.status = age
class Person2(object):
__slots__ = ("pid", "name", "age")
def __init__(self, pid, name, age):
self.pid = pid
self.name = name
self.age = age
if __name__ == '__main__':
p1 = Person1("111","p1","20")
p2 = Person2("222","p2","30")
p1.__dict__["level"] = 10 # __dict__ 为对象动态绑定属性,为对象p1 绑定新属性level {'pid': '111', 'name': 'p1', 'status': '20', 'level': 10}
print(p1.__dict__) # p1.__dict__ 打印的是当前对象所具有属性,是一个字典
print(sys.getsizeof(p1.__dict__))
# p2.__dict__["level"] = 20 # 会报错,p2不能绑定新属性,因为在Person2中使用了__slots__ = ()约定了三个属性
tracemalloc.start() # 开始跟踪内存分配
p1 = [Person1(23,24,25) for _ in range(100000)]
p2 = [Person2(30,31,32) for _ in range(100000)]
snapshot = tracemalloc.take_snapshot()
top = snapshot.statistics("filename")
for start in top[:10]:
print(start)
返回结果:
{'pid': '111', 'name': 'p1', 'status': '20', 'level': 10}
112
E:/pytestcode/slotstest.py:0: size=23.7 MiB, count=400004, average=62 B
D:\Python36\lib\tracemalloc.py:0: size=64 B, count=1, average=64 B
从返回结果中可以看出,使用__slots__ 定义一个元组,产生的对象占用的内存要小的多。
另外,在本例中我把__slots__ 定义为为一个列表和定义为一个元组,占用的内存大小差不多,这是在测试代码中。如果在正式的程序中,可能会提现的更明显。
当给p2另外绑定新属性时,会报错,如下:
Traceback (most recent call last):
File "E:/pytestcode/slotstest.py", line 27, in <module>
p2.__dict__["level"] = 20 # 会报错,p2不能绑定新属性,因为在Player2中使用了__slots__ = ()约定了三个属性
AttributeError: 'Person2' object has no attribute '__dict__'