python中的__slots__使用

如果我们想要限制实例的属性,Python允许在定义class的时候,定义一个特殊的slots变量,来限制该class实例能添加的属性。
使用slots要注意,slots定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
除非在子类中也定义slots,这样,子类实例允许定义的属性就是自身的slots加上父类的slots

# coding:utf-8
class Player(object):
    def __init__(self, uid, name, stat=0, level=1):
        self.uid = uid
        self.name = name
        self.stat = stat
        self.level = level


class Player2(object):
    __slots__ = ['uid', 'name', 'stat', 'level', 'sex']

    def __init__(self, uid, name, stat=0, level=1):
        self.uid = uid
        self.name = name
        self.stat = stat
        self.level = level


class Player3(Player2):
    def __init__(self, uid, name):
        super(Player3, self).__init__(uid, name)


class Player4(Player2):
    __slots__ = ['age']

    def __init__(self, uid, name):
        super(Player4, self).__init__(uid, name)
# 创建实例
p1 = Player('001', 'Jim')
p2 = Player2('002', 'Jim2')
p3 = Player3('003', 'Jim3')
p4 = Player4('004', 'Jim4')
# p1实例
print(p1.name)  # jim
p1.age = 16
print(p1.age)  # 16
# p2实例
print(p2.name)  # Jim2
p2.sex = 'boy'
print(p2.sex)  # boy
# p2.age = 16
# print(p2.age)  # 错误异常 AttributeError
# p3实例 __slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
print(p3.name)  # Jim3
p3.age = 16
print(p3.age)  # 16
# p4实例 
# 子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__
print(p4.name)  # Jim4
p4.age = 16
print(p4.age)  # 16
p4.sex = 'girl'
print(p4.sex)  # girl
# p4.date = '2019'
# print(p4.date)  # 错误异常 AttributeError

slots应用实例

如何为创建大量实例节省内存?

问题:某游戏中,定义了玩家类Player(uid, name, status...),每有一个在线玩家,在服务器程序内则有一个Player的实例,当在线人数很多时,将产生大量实例(如百万级)
解决方案:定义类的slots属性,它时用来声明实例属性名字的列表。

交互模式下看到p1和p2的属性,p1比p2使用的内存多,为什么呢,通过对比发现,属性多了__dict____weakref__

66433-cd16ce58f42f2b40.png

p1中的 p1.__dict__中是一个为实例动态绑定属性的字典
66433-37afcd4cb1f02d09.png

也可以直接往字典中给添加、删除属性
66433-e46dc6960caa9a3a.png

这种动态绑定属性是以牺牲内存为代价的
我们可以导入sys模块查看占用字节数

66433-11d5c4ba108949d0.png

所以,在创建对象的时候提前使用 __slots__提前声明好了所需的属性,就可以达到节省内存的目的

猜你喜欢

转载自blog.csdn.net/weixin_34123613/article/details/87254114