程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python創建大量實例時如何節省內存

編輯:Python

1、如何為創建大量實例節省內存?

        實際案例:

               某網絡游戲中,定義了玩家類Player(id, name, status, ...),每有一個在線玩家,在服務器程序內側有一個Player的實例,當在線人數很多時,將產生大量實例。(如百萬級)

                如何降低這些大量實例的內存開銷?

        解決方案:

                定義類的__slots__屬性,它是用來聲明實例屬性名字的列表,減少實例的__dict__字典從而達到節省內存開銷的目的。

2、代碼演示

class Player(object):
def __init__(self, uid, name, status=0, level=1):
self.uid = uid
self.name = name
self.status = status
self.level = level
class Player2(object):
# 定義__slots__變量,它用來聲明實例有哪些屬性
# 作用是阻止在實例化類時為實例分配dict
__slots__ = ['uid', 'name', 'status', 'level']
def __init__(self, uid, name, status=0, level=1):
self.uid = uid
self.name = name
self.status = status
self.level = level
'''
__slots__內置方法介紹:
(1)__slots__允許聲明並限定類成員,並拒絕創建__dict__
和__weakref__屬性以節約內存空間。
(2)在定義了__slots__變量後,類實例已經不能隨意創建不在_
_slots__定義的屬性,同時實例中也不再有__dict__結構。
(3)繼承樹:
子類未聲明__slots__時,不繼承父類的__slots__,
即此時子類可以隨意賦值屬性。
子類聲明了__slots__時,繼承父類的__slots__,即此時子類的
__slots__為其自身+父類的__slots__。
'''
# 創建Player和Player2的實例
p1 = Player('0001', 'Bob')
p2 = Player2('0001', 'Bob')
# p1比p2使用的內存要多,通過集合的差集查看
print(set(dir(p1)) - set(dir(p2)))
# 輸出結果為:{'__dict__', '__weakref__'}
'''
可以看出p1比p2多了__dict__和__weakref__屬性,在不使用弱引用的情況下
__weakref__並不會占用多少內存,最終占用都會落到__dict__上。
'''
# __dict__是為了實例動態綁定屬性的一個字典
print(p1.__dict__)
# 如p1沒有x屬性,為p1動態綁定一個x屬性
p1.x = 123
p1.__dict__['y'] = 99
# 可以發現x和y進入到字典當中去了
print(p1.__dict__)
# 也可以動態刪除(解除)
del p1.__dict__['y']
print(p1.__dict__)
'''
這樣一個動態綁定屬性的特性它是以犧牲內存為代價的,
為了節省內存關閉掉動態綁定屬性的特性就使用__slots__。
'''
import sys
# 得到一個對象使用的內存
print(sys.getsizeof(p1.__dict__))
'''
提前聲明好的在定義額外的屬性是不允許的。如:為p2綁定新的屬性,
會報錯 AttributeError: 'Player2' object has no attribute 'x'
這就類似於C語言的結構體,提前分配好了這些空間,這樣就達到了節省內存目的。
也就少了一個__dict__字典,__slots__副作用就是阻止動態屬性綁定。
'''
# p2.x = 123


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved