如何为创建大量实例节省内存?
Posted richardo-m-q
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何为创建大量实例节省内存?相关的知识,希望对你有一定的参考价值。
需求:
某网络游戏中,定义了玩家类Player(id,name,status,...)每有一个在线玩家,在服务器程序内则有一个Player的实例,当在线人数很多时,将产生大量实例(如百万级)
如何降低这些大量实例的内存开销?
思路:
定义类的__slots__属性,它是用来声明实例属性名字的列表。
代码:
e.py:
class Player(object):
def __init__(self,uid,name,status=0,level=1):
self.uid = uid
self.name = name
self.stat = status
self.level = level
class Player2(object):
__slots__ = [‘uid‘,‘name‘,‘stat‘,‘level‘] # 声明类实例化对象所有的属性名,禁止实例属性的动态绑定。即该实例没有了__dict__属性。
def __init__(self,uid,name,status=0,level=1):
self.uid = uid
self.name = name
self.stat = status
self.level = level
==============================================
测试:
In [3]: from e import Player, Player2
In [4]: p1 = Player(‘001‘,‘Jim‘)
In [5]: p2 = Player2(‘002‘,‘Tom‘)
In [6]: dir(p1)
Out[6]:
[‘__class__‘,
‘__delattr__‘,
‘__dict__‘,
‘__dir__‘,
‘__doc__‘,
‘__eq__‘,
‘__format__‘,
‘__ge__‘,
‘__getattribute__‘,
‘__gt__‘,
‘__hash__‘,
‘__init__‘,
‘__init_subclass__‘,
‘__le__‘,
‘__lt__‘,
‘__module__‘,
‘__ne__‘,
‘__new__‘,
‘__reduce__‘,
‘__reduce_ex__‘,
‘__repr__‘,
‘__setattr__‘,
‘__sizeof__‘,
‘__str__‘,
‘__subclasshook__‘,
‘__weakref__‘,
‘level‘,
‘name‘,
‘stat‘,
‘uid‘]
In [7]: dir(p2)
Out[7]:
[‘__class__‘,
‘__delattr__‘,
‘__dir__‘,
‘__doc__‘,
‘__eq__‘,
‘__format__‘,
‘__ge__‘,
‘__getattribute__‘,
‘__gt__‘,
‘__hash__‘,
‘__init__‘,
‘__init_subclass__‘,
‘__le__‘,
‘__lt__‘,
‘__module__‘,
‘__ne__‘,
‘__new__‘,
‘__reduce__‘,
‘__reduce_ex__‘,
‘__repr__‘,
‘__setattr__‘,
‘__sizeof__‘,
‘__slots__‘,
‘__str__‘,
‘__subclasshook__‘,
‘level‘,
‘name‘,
‘stat‘,
‘uid‘]
In [8]: set(dir(p1)) - set(dir(p2)) # 取集合的差集,这里是p1比p2多的属性
Out[8]: {‘__dict__‘, ‘__weakref__‘}
In [9]: set(dir(p2)) - set(dir(p1))
Out[9]: {‘__slots__‘}
In [10]: p1.__dict__ # 这里__dict__是一个动态的字典
Out[10]: {‘uid‘: ‘001‘, ‘name‘: ‘Jim‘, ‘stat‘: 0, ‘level‘: 1}
In [11]: p1.x
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-11-54f8378113e3> in <module>
----> 1 p1.x
AttributeError: ‘Player‘ object has no attribute ‘x‘
In [12]: p1.x = 123 # 可以动态的增加属性
In [13]: p1.x
Out[13]: 123
In [14]: p1.__dict__
Out[14]: {‘uid‘: ‘001‘, ‘name‘: ‘Jim‘, ‘stat‘: 0, ‘level‘: 1, ‘x‘: 123}
In [15]: p1.__dict__[‘y‘] = 99
In [16]: p1.y
Out[16]: 99
In [17]: del p1.__dict__[‘x‘] # 删除属性
In [18]: p1.x
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-18-54f8378113e3> in <module>
----> 1 p1.x
AttributeError: ‘Player‘ object has no attribute ‘x‘
In [19]: import sys
In [20]: sys.getsizeof(p1.__dict__) # 获取该属性所占用的内存空间,所以禁用该属性后占用的内存空间减少
Out[20]: 368
In [21]: p2.x = 123
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-21-2c5f7091e7e8> in <module>
----> 1 p2.x = 123
AttributeError: ‘Player2‘ object has no attribute ‘x‘
In [22]: sys.getsizeof(p2.__slot__)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-22-d68996e840e6> in <module>
----> 1 sys.getsizeof(p2.__slot__)
AttributeError: ‘Player2‘ object has no attribute ‘__slot__‘
In [23]: sys.getsizeof(p2.__slots__)
Out[23]: 96
以上是关于如何为创建大量实例节省内存?的主要内容,如果未能解决你的问题,请参考以下文章