python手动垃圾回收_Python3学习笔记,F,垃圾,回收
筆記中代碼均可運行在Jupyter NoteBook下(實際上Jupyter-lab使用體驗也很棒)。
建議不要光看,要多動手敲代碼。眼過千遭,不如手讀一遍。
相關筆記的jupiter運行代碼已經上傳,請在資源中自行下載。
垃圾回收
參考網址:https://www.cnblogs.com/jin-xin/articles/9439483.html
概括:
同一代碼塊下:緩存機制
不同代碼塊:小數據池
代碼塊
一個模塊、一個函數、一個類、一個文件都是一個代碼塊。
在交互式命令行下,一個命令就是一個代碼塊。
代碼塊的緩存機制
Python在執行同一個代碼塊的初始化對象的命令時,
會檢查是否其值是否已經存在,如果存在,會將其重用。
換句話說:
執行同一個代碼塊時,遇到初始化對象的命令時,
他會將初始化的這個變量與值存儲在一個字典中,
在遇到新的變量時,會先在字典中查詢記錄,
如果有同樣的記錄那么它會重復使用這個字典中的之前的這個值。
滿足緩存機制則他們在內存中只存在一個,即:id相同。
代碼塊的緩存機制的適用范圍: int(float),str,bool。
int(float):任何數字在同一代碼塊下都會復用。
bool:True和False在字典中會以1,0方式存在,并且復用。
str:幾乎所有的字符串都會符合緩存機制
1,非乘法得到的字符串都滿足代碼塊的緩存機制
2,乘法得到的字符串分兩種情況:
2.1 乘數為1時,任何字符串滿足代碼塊的緩存機制:
2.2 乘數>=2時:僅含大小寫字母,數字,下劃線,
總長度<=20,滿足代碼塊的緩存機制
優點:
能夠提高一些字符串,整數處理人物在時間和空間上的性能;
需要值相同的字符串,整數的時候,直接從‘字典’中取出復用,避免頻繁創建和銷毀,提升效率,節約內存。
'''jupyter這里運行存在問題,以注釋為主'''
# 字符串緩存機制 例子
# 非乘法得到的字符串
def unMult():
s1 = 'string'
s2 = 'string'
print('非乘法得到的字符串')
print('*'*30)
print('s1和s2地址比較:',id(s1) == id(s2)) # True
print('*'*30)
# 乘數為1得到的字符串
def multOne():
s3 = 'asdf!@#$%^*'*1
s4 = 'asdf!@#$%^*'*1
print('乘數為1得到的字符串')
print('*'*30)
print('s3和s4地址比較:',id(s3) == id(s4)) # True
print('*'*30)
# 乘數>=2時
def multMore():
s3 = 'adf!'*4 # 包含其他字符,總長<20
s4 = 'adf!'*4
s5 = 'qwertyuiop[]asdfghjk!@#$%^&'*4
# 包含其他字符,總長>20
s6 = 'qwertyuiop[]asdfghjk!@#$%^&'*4
s7 = 'asdf_asdf'*3 # # 不包含其他字符,總長<20
s8 = 'asdf_asdf'*3
print('乘數為>=2,總長度<=20,包含其他字符得到的字符串')
print('*'*30)
print('s3和s4地址比較:',id(s3) == id(s4)) # False
print('*'*30)
print('乘數為>=2,總長度>20,包含其他字符得到的字符串')
print('*'*30)
print('s5和s6地址比較:',id(s5) == id(s6)) # False
print('*'*30)
print('乘數為>=2,總長度<=20,不包含其他字符得到的字符串')
print('*'*30)
print('s7和s8地址比較:',id(s7) == id(s8)) # True
print('*'*30)
# test
unMult()
multOne()
multMore()
非乘法得到的字符串
******************************
s1和s2地址比較: True
s1和s2來源比較: True
******************************
乘數為1得到的字符串
******************************
s3和s4地址比較: True
s3和s4來源比較: True
******************************
乘數為>=2,總長度<=20,包含其他字符得到的字符串
******************************
s3和s4地址比較: True
s3和s4來源比較: True
******************************
乘數為>=2,總長度>20,包含其他字符得到的字符串
******************************
s5和s6地址比較: True
s5和s6來源比較: True
******************************
乘數為>=2,總長度<=20,不包含其他字符得到的字符串
******************************
s7和s8地址比較: True
s7和s8來源比較: True
******************************
小數據池
大前提:
小數據池也是只針對 int(float),str,bool。
小數據池是針對不同代碼塊之間的緩存機制!!!
Python自動將-5~256的整數進行了緩存,
當你將這些整數賦值給變量時,并不會重新創建對象,
而是使用已經創建好的緩存對象。
python會將一定規則的字符串在字符串駐留池中創建一份。
'''小數據池例子'''
# 整數
a = 100
b = 100
c = 123456
d = 123456
print('id(a) == id(b): ',id(a) == id(b))
print('id(c) == id(d): ',id(c) == id(d))
id(a) == id(b): True
id(c) == id(d): False
指定駐留
# 指定駐留 例子
from sys import intern
a = 'asd*&'*3
b = 'asd*&'*3
print('未指定駐留:a is b:', a is b)
print(id(a))
print(id(b))
c = intern('asd*&'*3)
d = intern('asd*&'*3)
print('指定駐留:c is d:', c is d)
print(id(c))
print(id(d))
未指定駐留:a is b: False
139839647396976
139839643255088
不未指定駐留:c is d: True
139839642805680
139839642805680
引用計數
Python中以引用計數為主:
引用計數優點:簡單,實時性
引用計數缺點:維護時占用內存,循環引用,造成內存泄漏
引用計數減一不止del,還可以透過賦值None
隔代回收
Ruby中的垃圾回收是標記清除,對內存的申請是一次申請多個,
當內存不夠用時再清理,而Python中的內存申請是用一個申請一個。
隔代回收為輔:
零代鏈表中檢測到相互循環引用的減一,得到是否是垃圾(引用計數為0),需要回收,否則不會減一
GC模塊
'''
gc.get_count():獲取當前自動執行垃圾回收的計數器
返回一個元組(x,y,z)
參數解釋:
[
x 表示內存占用,
y 表示零代清理次數,
z 同理表示1代清理次數
]
gc.get_threshold() 獲取的gc模塊中自動執行垃圾回收的頻率
返回(x,y,z)
參數解釋:
[
x表示清理上限,
y表示每清理零代鏈表10次,
清理一次 1 代鏈表。
z同理是1,2代 這里的x,y,z默認值為(700,10,10)
]
查看一個對象的引用計數:
sys.getrefcount()
gc.disable() 關閉Python的gc
gc.enable() 開啟gc
gc.isenabled() 判斷是否是開啟gc的
gc.collect([generation])顯式進行垃圾回收(手動回收)
可以輸入參數:
[
0代表只檢查第一代的對象,
1代表檢查一,二代的對象,
2代表檢查一,二,三代的對象,
如果不傳參數,執行一個full collection,也就是等于傳2。
]
注意:
盡量不要手動重寫對象的__del__方法,
因為重寫后會使刪除時不會自動調用gc來刪除,
此時需要調用父類的__del__()來刪除
'''
# gc 引用計數 示例
import gc, sys
a = 1
get_a_c = sys.getrefcount(a)
b = a
get_b_c = sys.getrefcount(a)
gc_c = gc.get_count()
gc_t = gc.get_threshold()
gc.disable()
gc.enable()
gc_is = gc.isenabled()
gc_cl = gc.collect(2)
print(get_a_c, get_b_c, gc_c, gc_t, gc_is, gc_cl)
2275 2275 (603, 5, 0) (700, 10, 10) True 921
總結
以上是生活随笔為你收集整理的python手动垃圾回收_Python3学习笔记,F,垃圾,回收的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 笔记:linux中tcp_tw_reus
 - 下一篇: 架构探险-从零开始写Javaweb框架读