2.Python 賦值與內存


 

定義變量和賦值就是系統處理內存的過程和問題,這篇文章分別從申請和釋放內存兩部分討論

 

一、申請內存

 

python定義一個變量時,會為變量的對象申請一個內存,該變量會存儲指向該對象內存中的地址

這樣的好處是復用共同內容對象,節省內存空間

In [1]:
name = 'admin'
print("name=", name)

name1 = name
print("name1=", name1)
 
name= admin
name1= admin
In [2]:
name2 = 'admin'
print("name2=", name2)
 
name2= admin
In [3]:
print(id(name), name)
print(id(name1), name1)
print(id(name2), name2)
 
2951857458848 admin
2951857458848 admin
2951857458848 admin
 

如圖:定義了name變量,賦值為“admin”,然后將name賦值給name1,則name1擁有了與name相同的值。再定義另一個變量name2,將name2的值設值為“admin”。也就是name,name1和name2值都為“admin”。則系統賦值運行的過程如下:

1.系統會申請一個內存,存放“admin”

2.將name,name1和name2共用“admin”這個內存

 

 

In [4]:
name2 = name
print(name == name2)
print(id(name) == id(name2))
 
True
True
In [5]:
name2 = "admin1"
print(id(name), name)
print(id(name2), name2)

print(name == name2)
print(id(name) == id(name2))
 
2951857458848 admin
2951857622744 admin1
False
False
 

上面兩塊代碼驗證了在python系統中,變量會共用相同的值的內存。

1.當name2的值與name的值為“admin”時,name2與name對象的內存地址相同。

2.當name2的值改變為“admin1”時,name2對象的內存地址將會改變了

 

 

 

二、釋放內存

 

Python的內存管理主要有三種機制:引入計數機制、垃圾回收機制和內存池機制。

引入技術機制:在python內部,通過引入技術來保持追蹤內存中的對象,python內部記錄對象有多少個引用,即引用計數,當對象被創建使就創建一個引用計數,當對象不再需要時,這個對象的引用計數為0時,它將被垃圾回收。

垃圾回收機制:當內存中不再使用該內存部分時,垃圾收集器就會把它們清理掉。它會去檢查引用計數為0的對象,然后清除其所在的內存的空間。

內存池機制:在Python中,許多時候申請的內存都是小塊的內存,這些小塊內存在申請后,很快又會被釋放,由於這些內存的申請並不是為了創建對象,所以並沒有對象一級的內存池機制。這就意味着Python在運行期間會大量地執行malloc和free的操作,頻繁地在用戶態和核心態之間進行切換,這將嚴重影響Python的執行效率。為了加速Python的執行效率,Python引入了一個內存池機制,用於管理對小塊內存的申請和釋放。內存池的概念就是預先在內存中申請一定數量的,大小相等的內存塊留作備用,當有新的內存需求時,就先從內存池中分配內存給這個需求,不夠了之后再申請新的內存。這樣做最顯著的優勢就是能夠減少內存碎片,提升效率。內存池的實現方式有很多,性能和適用范圍也不一樣。

下面通過三個步驟分析內存管理和釋放的過程:

 

步驟1:將name2和name1的值都更變為“admin1”,可以發現,name1和name2的對象都為“admin1”,name1和name2打印出來的對象內存地址都是相同的。而name對象為“admin”,name打印出來的內存地址與另外兩個不同。

In [6]:
name2 = 'admin1'
In [7]:
name1 = name2
print(id(name1), name1)
print(id(name2), name2)

print(id(name), name)
 
2951857622744 admin1
2951857622744 admin1
2951857458848 admin
 

步驟2:將name的對象也更變為“admin1”,再從新打印發現name,name1和name2的地址一樣了。

In [8]:
name = 'admin1'
print(id(name1), name1)
print(id(name2), name2)
print(id(name),name)
 
2951857622744 admin1
2951857622744 admin1
2951857622744 admin1
 

步驟3:重新申請name並復制為“admin”,打印出來后,發現該步驟中打印的name的對象內存地址與步驟一種打印name的內存地址變得不一樣了。

In [9]:
name = 'admin'

print(id(name1), name1)
print(id(name2), name2)
print(id(name),name)
 
2951857622744 admin1
2951857622744 admin1
2951857632064 admin


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM