案例:
某网络游戏中,定义了玩家类Player(id, name, status,....),每有一个在线玩家,在服务器程序内有一个Player的实例,当在线人数很多时,将产生大量实例(百万级别)
需求:
如何降低这些大量实例的内存开销?
如何做?
首先要明白,python中的类可以动态的添加属性,实则在内存中有个__dict__方法维护了这种动态添加属性,它占有内存,把它关掉,不就达到省内存要求了?
# -*- coding: utf-8 -*- """ @author:songhao @file: c3.py @time: 2017/12/08 """ import sys class Payer: def __init__(self, id, name, status=1, level=0): self.id = id self.name = name self.status = status self.level = level class Payer2: __<span class="wp_keywordlink_affiliate"><a href="https://www.168seo.cn/tag/slots" title="View all posts in slots" target="_blank">slots</a></span>__ = ["id", "name", "status", "level"] def __init__(self, id, name, status=1, level=0): self.id = id self.name = name self.status = status self.level = level def main(): pass if __name__ == '__main__': p = Payer(1, "songhao") print(sys.getsizeof(p)) print(p.__dict__) # 为p实例添加 变量 p.x = "xsonghao" print(p.x) print(p.__dict__) # 删除属性 del p.x print(p.__dict__) # 打印__dict__占用的内存空间 print(sys.getsizeof(p.__dict__)) print("分割符__<span class="wp_keywordlink_affiliate"><a href="https://www.168seo.cn/tag/slots" title="View all posts in slots" target="_blank">slots</a></span>__".center(50, "*")) p2 = Payer2(1, "songhao") # print(p2.__dict__) """ Traceback (most recent call last): File "/Users/songhao/Desktop/Python3 入门和进阶/Python file/d11/c3.py", line 46, in <module> print(p2.__dict__) AttributeError: 'Payer2' object has no attribute '__dict__' """ print(sys.getsizeof(p2)) #p2.x = "xsonghao" """ {'id': 1, 'name': 'songhao', 'status': 1, 'level': 0, 'x': 'xsonghao'} p2.x = "xsonghao" {'id': 1, 'name': 'songhao', 'status': 1, 'level': 0} AttributeError: 'Payer2' object has no attribute 'x' """
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
# -*- coding: utf-8 -*-
"""
@author:songhao
@file: c3.py
@time: 2017/12/08
"""
import
sys
class
Payer
:
def
__init__
(
self
,
id
,
name
,
status
=
1
,
level
=
0
)
:
self
.
id
=
id
self
.
name
=
name
self
.
status
=
status
self
.
level
=
level
class
Payer2
:
__slots__
=
[
"id"
,
"name"
,
"status"
,
"level"
]
def
__init__
(
self
,
id
,
name
,
status
=
1
,
level
=
0
)
:
self
.
id
=
id
self
.
name
=
name
self
.
status
=
status
self
.
level
=
level
def
main
(
)
:
pass
if
__name__
==
'__main__'
:
p
=
Payer
(
1
,
"songhao"
)
print
(
sys
.
getsizeof
(
p
)
)
print
(
p
.
__dict__
)
# 为p实例添加 变量
p
.
x
=
"xsonghao"
print
(
p
.
x
)
print
(
p
.
__dict__
)
# 删除属性
del
p
.
x
print
(
p
.
__dict__
)
# 打印__dict__占用的内存空间
print
(
sys
.
getsizeof
(
p
.
__dict__
)
)
print
(
"分割符__slots__"
.
center
(
50
,
"*"
)
)
p2
=
Payer2
(
1
,
"songhao"
)
# print(p2.__dict__)
"""
Traceback (most recent call last):
File "/Users/songhao/Desktop/Python3 入门和进阶/Python file/d11/c3.py", line 46, in <module>
print(p2.__dict__)
AttributeError: 'Payer2' object has no attribute '__dict__'
"""
print
(
sys
.
getsizeof
(
p2
)
)
#p2.x = "xsonghao"
"""
{'id': 1, 'name': 'songhao', 'status': 1, 'level': 0, 'x': 'xsonghao'}
p2.x = "xsonghao"
{'id': 1, 'name': 'songhao', 'status': 1, 'level': 0}
AttributeError: 'Payer2' object has no attribute 'x'
"""
|
输出:
当你定义 __slots__ 后,Python就会为实例使用一种更加紧凑的内部表示。 实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个字典,这跟元组或列表很类似。 在 __slots__ 中列出的属性名在内部被映射到这个数组的指定小标上。 使用slots一个不好的地方就是我们不能再给实例添加新的属性了,只能使用在 __slots__ 中定义的那些属性名。