由於python中萬物皆物件,所以python的儲存問題是物件的儲存問題,並且對於每個物件,python會分配一塊記憶體空間去儲存它
注意:
變數名沒有型別,型別屬於物件(因為變數引用物件,所以型別隨物件),變數引用什麼型別的物件,變數就是什麼型別的。
a = 123
b = a
print(id(a))
print(id(b))
a = 456
print(id(a))
print(id(b))
通過is進行引用所指判斷,is是用來判斷兩個引用所指的物件是否相同
整數:
a = 1
b = 1
print(a is b) # true
短字串:
c = "good"
d = "good"
print(c is d) # true
長字串:
e = "very good"
f = "very good"
print(e is f) # false
列表:
g =
h =
print(g is h) # false
由執行結果可知:python快取了整數和短字串,因此每個物件在記憶體中只存有乙份,引用所指物件就是相同的,即使使用賦值語句,也只是創造新的引用,而不是物件本身;
python沒有快取長字串、列表及其他物件,可以由多個相同的物件,可以使用賦值語句建立出新的物件。
在python中,每個物件都有指向該物件的引用總數---引用計數
檢視物件的引用計數:sys.getrefcount()
import sys
a = [1, 2, 3]
print(sys.getrefcount(a)) # 2
b = 2
print(sys.getrefcount(a)) # 3
print(sys.getrefcount(b)) # 3
注意:當使用某個引用作為引數,傳遞給getrefcount()
時,引數實際上建立了乙個臨時的引用。getrefcount()
所得到的結果,會比期望的多1。
python的乙個容器物件(比如:表、詞典等),可以包含多個物件
由上可見,實際上,容器物件,如列表、元組、字典等,儲存的其它物件,僅僅是對其它物件的引用,即位址,並不是這些物件本身
物件被建立,引用計數增加1
物件被引用,增加1
作為容器的物件,增加1
物件被當作引數傳入函式func(object)
,增加2
import sys
# 物件被建立
obj = "i love python, i want to be a good programmer!"
print(sys.getrefcount(obj) - 1) # 3
# 被引用
m = obj
print(sys.getrefcount(obj) - 1) # 4
p = m
print(sys.getrefcount(obj) - 1) # 5
# 作為容器物件的乙個元素
a = ["a", "b", obj]
print(sys.getrefcount(obj) - 1) # 6
def foo(x):
z = "hello world! "
print(sys.getrefcount(obj) - 1) # 8
print(z)
foo(obj)
print(sys.getrefcount(obj) - 1) # 6 函式執行完畢後區域性命名空間被銷毀,引用計數減少
物件的別名被顯式減少del obj
物件的乙個別名被賦值給其它物件
物件從乙個容器物件中移除,或,容器物件本身被銷毀
乙個本地引用離開了它的作用域,比如上面的foo(x)函式結束時,x指向的物件引用減1
作用:
當python中的物件越來越多,佔據越來越大的記憶體,啟動垃圾**garbage collection
,將沒用的物件清除
作用:
垃圾**檢測流程:
如何找到迴圈引用並釋放記憶體:
收集所有容器物件(迴圈引用只針對容器物件,其它物件不會產生迴圈引用),使用雙向鍊錶(可以看作乙個集合)對這些容器物件進行引用
針對每乙個容器物件,使用變數gc_refs
來記錄當前對應的引用個數
針對每乙個容器物件,找到其正在引用的其它容器物件,並將這個被引用的容器物件引用計數減去1
檢查所有容器物件的引用計數,若為0,則證明該容器物件是由於迴圈引用存活下來的,並對其進行銷毀
提公升查詢迴圈引用的效能:
分代**機制:
預設乙個物件被建立出來後,屬於0代
如果經歷過這一代「垃圾**」後,依然存活,則劃分為下一代
「垃圾**」的週期順序為
0代「垃圾**」一定次數,會觸發0代和1代**
1代「垃圾**」一定次數,會觸發0代,1代和2代**
通過這個分代**機制,迴圈引用處理過程就會得到很大的效能提公升
自動**:
手動**:這裡要使用gc
模組中的collect()
方法,使得執行這個方法時執行分代**機制
import objgraph, gc, sys # objgraph模組的count()方法是記錄當前類產生的例項物件的個數
class person(object):
pass
class dog(object):
pass
p = person()
d = dog()
print(sys.getrefcount(p) - 1, sys.getrefcount(d) - 1) # 1, 1
p.pet = d
d.master = p
print(sys.getrefcount(p) - 1, sys.getrefcount(d) - 1) # 2, 2
del p, d
print(objgraph.count("person"), objgraph.count("dog")) # 1, 1
gc.collect()
print(objgraph.count("person"), objgraph.count("dog")) # 0, 0
python中有分為大記憶體和小記憶體:(256k為界限分大小記憶體)
大記憶體使用malloc進行分配
小記憶體使用記憶體池進行分配
python的記憶體(金字塔):
python的記憶體管理機制就是引用計數器機制和垃圾**機制的混合機制
Python記憶體管理機制
一 python記憶體 因為要呼叫while迴圈,迴圈內有temp變數,不清楚python是否會在每一輪迴圈結束後自動釋放temp記憶體空間,做了乙個記憶體測試,發現無論temp none,還是del temp,只能銷毀變數,無法完全釋放記憶體空間。注 紅色部分標出相同記憶體id。python vi...
python記憶體管理機制
a 1整數1為乙個物件。而a是乙個引用。利用賦值語句,引用a指向物件1。在python中,整數和短小的字元,python都會快取這些物件,以便重複使用。當我們建立多個等於1的引用時,實際上是讓所有這些引用指向同乙個物件。a 1 b 1 print id a print id b 在python中,每...
python記憶體管理機制
1.引用計數 當乙個python物件被引用時 其引用計數增加 1 當其不再被變數引用時 引用計數減 1 當物件引用計數等於 0 時,物件被刪除 引用計數是一種非常高效的記憶體管理機制 2.垃圾 垃圾 機制 引用計數 標記清除 分帶 引用計數 引用計數也是一種垃圾收集機制,而且也是一種最直觀,最簡單的...