python 是一门动态语言,对于每一个类来说,我们可以在运行的过程中修改每个实例的属性和方法。
如果我们不想实例属性被改变,使用固定属性,这是可以使用__slots__属性去实现。
class Player1(object):
def __init__(self, name, type, hp, money):
self.name = name
self.type = type
self.hp = hp
self.money = money
class Player2(object):
__slots__ = ('name', 'tp', 'hp', 'money')
def __init__(self, name, tp, hp, money):
self.name = name
self.tp = tp
self.hp = hp
self.money = money
p1 = Player1('狂魔', '狂战士', 100, 0) # 实例一个Player1对象
p2 = Player2('大仙', '法师', 150, 0) # 实例一个Player2对象
# 查看两个类的属性、方法列表
print(dir(p1)) # p1有__dict__方法
print(dir(p2)) # p2没有__weakref__和__dict__方法,多了一个__slots__方法
"""
为p1动态绑定属性
"""
p1.__dict__['level'] = 1 # 动态为p1添加属性
print(p1.__dict__)
"""
p2不能动态绑定属性
"""
# p2.level = 1 # 添加失败,'Player2' object has no attribute 'level'
p2.__slots__ = (1,) # 'Player2' object attribute '__slots__' is read-only,报错,只读属性
__slots__
的另一个作用是可以降低大量实例的内存开销,这里借助一个模块tracemalloc来跟踪内存的使用情况
import tracemalloc
class Player1(object):
def __init__(self, name, type, hp, money):
self.name = name
self.type = type
self.hp = hp
self.money = money
class Player2(object):
__slots__ = ('name', 'tp', 'hp', 'money')
def __init__(self, name, tp, hp, money):
self.name = name
self.tp = tp
self.hp = hp
self.money = money
tracemalloc.start() # 开始跟踪内存分配
# p1 = [Player1(1, 2, 3, 4) for _ in range(10000)] # 占用内存情况size=1566 KiB, count=29935, average=54 B
p2 = [Player2(1, 2, 3, 4) for _ in range(10000)] # 占用内存情况size=711 KiB, count=10003, average=73 B
snapshot = tracemalloc.take_snapshot() # 快照,当前内存分配
top = snapshot.statistics('filename') # 对象统计
for start in top[:10]:
print(start)
从上面代码的结果可以知道,使用__slots__
属性可以降低内存的开销。
__slots__
不影响子类实例,不会继承,除非子类里面自己定义了 __slots__
最后,有喜欢博主写的内容的伙伴可以收藏加关注哦!