Python深入之python記憶體管理機制(重點)

来源:https://www.cnblogs.com/chengxuyuanaa/archive/2019/12/03/11979857.html

前言本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。 作者:醍醐三葉 關於python的存儲問題, (1)由於python中萬物皆對象,所以python的存儲問題是對象的存儲問題,並且對於每個對象,python會分配一塊記憶體空間去 ...


前言

本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。

 

關於python的存儲問題,

(1)由於python中萬物皆對象,所以python的存儲問題是對象的存儲問題,並且對於每個對象,python會分配一塊記憶體空間去存儲它

(2)對於整數和短小的字元等,python會執行緩存機制,即將這些對象進行緩存,不會為相同的對象分配多個記憶體空間,如果對我講的還不懂,說明你基礎學的還不是和很好,可以去小編的Python交流.裙 :一久武其而而流一思(數字的諧音)轉換下可以找到了,裡面很多最新Python精講的教程項目。

(3)容器對象,如列表、元組、字典等,存儲的其他對象,僅僅是其他對象的引用,即地址,並不是這些對象本身

關於引用計數器

(1)一個對象會記錄著引用自己的對象的個數,每增加一個引用,個數加一,每減少一個引用,個數減一

(2)查看引用對象個數的方法:導入sys模塊,使用模塊中的getrefcount(對象)方法,由於這裡也是一個引用,故輸出的結果多1

(3)增加引用個數的情況:1.對象被創建p = Person(),增加1;2.對象被引用p1 = p,增加1;3.對象被當作參數傳入函數func(object),增加2,原因是函數中有兩個屬性在引用該對象;4.對象存儲到容器對象中l = [p],增加1

(4)減少引用個數的情況:1.對象的別名被銷毀del p,減少1;2.對象的別名被賦予其他對象,減少1;3.對象離開自己的作用域,如getrefcount(對象)方法,每次用完後,其對對象的那個引用就會被銷毀,減少1;4.對象從容器對象中刪除,或者容器對象被銷毀,減少1

(5)引用計數器用法:

import sys
class Person(object):
    pass
p = Person()
p1 = p
print(sys.getrefcount(p))
p2 = p1
print(sys.getrefcount(p))
p3 = p2
print(sys.getrefcount(p))
del p1
print(sys.getrefcount(p))

多一個引用,結果加1,銷毀一個引用,結果減少1

(6)引用計數器機制:利用引用計數器方法,在檢測到對象引用個數為0時,對普通的對象進行釋放記憶體的機制

關於迴圈引用問題,如果對我講的還不懂,說明你基礎學的還不是和很好,可以去小編的Python交流.裙 :一久武其而而流一思(數字的諧音)轉換下可以找到了,裡面很多最新Python精講的教程項目。

(1)迴圈引用即對象之間進行相互引用,出現迴圈引用後,利用上述引用計數機制無法對迴圈引用中的對象進行釋放空間,這就是迴圈引用問題

(2)迴圈引用形式:

class Person(object):
    pass
class Dog(object):
    pass
p = Person()
d = Dog()
p.pet = d
d.master = p

即對象p中的屬性引用d,而對象d中屬性同時來引用p,從而造成僅僅刪除p和d對象,也無法釋放其記憶體空間,因為他們依然在被引用。深入解釋就是,迴圈引用後,p和d被引用個數為2,刪除p和d對象後,兩者被引用個數變為1,並不是0,而python只有在檢查到一個對象的被引用個數為0時,才會自動釋放其記憶體,所以這裡無法釋放p和d的記憶體空間

關於垃圾回收(底層層面--原理)

(1)垃圾回收的作用:從經過引用計數器機制後還沒有被釋放掉記憶體的對象中,找到迴圈引用對象,並釋放掉其記憶體

(2)垃圾回收檢測流程:

一.任何找到迴圈引用並釋放記憶體:1.收集所有容器對象(迴圈引用只針對於容器對象,其他對象不會產生迴圈引用),使用雙向鏈表(可以看作一個集合)對這些對象進行引用;2.針對每一個容器對象,使用變數gc_refs來記錄當前對應的應用個數;3.對於每個容器對象,找到其正在引用的其他容器對象,並將這個被引用的容器對象引用計數減去1;4.經過步驟3後,檢查所有容器對象的引用計數,若為0,則證明該容器對象是由於迴圈引用存活下來的,並對其進行銷毀

二.如何提升查找迴圈引用過程的性能:由一可知,迴圈引用查找和銷毀過程非常繁瑣,要分別處理每一個容器對象,所以python考慮一種改善性能的做法,即分代回收。首先是一個假設--如果一個對象被檢測了10次還沒有被銷毀,就減少對其的檢測頻率;基於這個假設,提出一套機制,即分代回收機制。

通過這個機制,迴圈引用處理過程就會得到很大的性能提升

關於垃圾回收時機(應用層面--重點)

(1)自動回收:

(2)手動回收:這裡要使用gc模塊中的collect()方法,使得執行這個方法時執行分代回收機制

import objgraph
import gc
import sys
class Person(object):
    pass
class Dog(object):
    pass
p = Person()
d = Dog()
p.pet = d
d.master = p
del p
del d
gc.collect()
print(objgraph.count("Person"))
print(objgraph.count("Dog"))

其中objgraph模塊的count()方法是記錄當前類產生的實例對象的個數

關於記憶體管理機制的總結(重點)

綜上所述,python的記憶體管理機制就是引用計數器機制和垃圾回收機制的混合機制


您的分享是我們最大的動力!

更多相關文章
  • LinkedList實現原理(JDK1.8) LinkedList底層採用雙向鏈表,如果對鏈表這種結構比較熟悉的話,那LinkedList的實現原理看明白就相當容易。 鏈表通過“指針”將一組零散的記憶體塊串聯起來使用,每一個元素(節點)通過指針指向它的下一個元素,最後一個節點的下一個指向為null,而 ...
  • Java抽象類: 抽象類特點 :抽象類除了不能實例化對象之外,類的其它功能依然存在,成員變數、成員方法和構造方法的訪問方式和普通類一樣。 由於抽象類不能實例化對象,所以抽象類必須被extends [抽象類]方式 繼承才能被使用。 抽象類表示的是一種繼承關係。 (總結就是:抽象類裡面設計跟普通類一樣, ...
  • lua中json和table的互轉,是我們在平時開發過程中經常用到的。比如: 在用lua編寫的伺服器中,如果客戶端發送json格式的數據,那麼在lua處理業務邏輯的時候,必然需要轉換成lua自己的數據結構,如table。此時,就會用到table和json格式的互轉。 在用lua編寫的伺服器中,如果我 ...
  • 先定義消息類型 orders.proto 在GOPATH創建目錄和編譯這個消息類型輸出到該目錄,包名是message 編寫go文件進行序列化和反序列化剛纔生成的包里的類型結構體數據 ...
  • swap(a,b) 用於交換a,b兩個變數的值; max(a,b) 返回a,b中的最大值; min(a,b) 返回a,b中的最小值; abs(x) 返回x的絕對值,x必須是整數; ...
  • ——日拱一卒,不期而至! 你好,我是彤哥,本篇是netty系列的第六篇。 簡介 上一章我們一起學習了Java NIO的核心組件Channel,它可以看作是實體與實體之間的連接,而且需要與Buffer交互,這一章我們就來學習一下Buffer的特性。 概念 Buffer用於與Channel交互時使用,通 ...
  • 前言 "上文" 我們介紹了JDK中的線程池框架 。我們知道,只要需要創建線程的情況下,即使是在單線程模式下,我們也要儘量使用 。即: 但是,在 "《阿裡巴巴Java開發手冊》" 中有一條 【強制】線程池不允許使用 Executors 去創建,而是通過 ThreadPoolExecutor 的方式,這 ...
  • PyCharm 是一種 Python IDE,可以幫助程式員節約時間,提高生產效率。那麼具體如何使用呢?本文從 PyCharm 安裝到插件、外部工具、專業版功能等進行了一一介紹,希望能夠幫助到大家。 機器之心之前也沒系統地介紹過 PyCharm,怎樣配置環境、怎樣 DeBug、怎樣同步 GitHub ...
一周排行
  • 本文將介紹如何在.NET Core3環境下使用MVVM框架Prism的使用事件聚合器實現模塊間的通信 一.事件聚合器 在上一篇 ".NET Core 3 WPF MVVM框架 Prism系列之模塊化" 我們留下了一些問題,就是如何處理同模塊不同窗體之間的通信和不同模塊之間不同窗體的通信,Prism提 ...
  • Microsoft Visual Studio 2010 的項目為件改為Microsoft Visual Studio 2015預設打開 2010 的Solution (.Sln) file 更改為 2015 的Solution (.Sln) file ...
  • 設計一個簡單的登錄視窗,要求輸入用戶名:小金,密碼:123456時候點登錄能正確轉到另一個視窗。 1、建立窗體應用。 2、這裡創建一個login和一個NewForm的窗體。 3、在login的窗體拖拉2個label和2個textbox和1個linklabel的控制項。一個標簽名字為用戶名,一個標簽為密 ...
  • 已有站點:HTTP80 %systemroot%\system32\inetsrv\APPCMD ADD APP /SITE.NAME:"HTTP80" /path:/Redirect /physicalPath:"C:\Windows\System32\drivers\etc" /applicat ...
  • ``` var xmlstr = @" some_appid 1413192605 component_verify_ticket some_verify_ticket "; Stopwatch sw = Stopwatch.StartNew(); for (int i = 0; i ...
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7640873.html,記錄一下學習過程以備後續查用。 一、引言 很多人說原型設計模式會節省機器記憶體,他們說是拷貝出來的對象是原型的複製,不會使用記憶體。我認為這是不對的,因為拷貝出來的每一個對象都是實際 存在的 ...
  • 實現把String字元串轉化為In後可用參數代碼: public string StringToList(string aa) { string bb1 = "("; if (!string.IsNullOrEmpty(aa.Trim())) { string[] bb = aa.Split(new ...
  • 1.ImportData主方法 把傳入為object數組類型,按照下標取出對應的參數,此處為Table和Username public object[] ImportData(object[] Param) { DataTable dt = (DataTable)Param[0]; string m ...
  • C#實現對Excel操作,根據數據的類型不同或者來源不同會放在不同的頁簽中,C#實現添加頁簽代碼如下:(path為文檔保存的地址,dt為要處理的源數據) public void addSheet(string Path, DataTable dt) { var SlDoc = new SLDocum ...
  • public partial class Form1 : Form { public Form1() { InitializeComponent(); Dog dog = new Dog(); InsertDog(dog); dog.OnAlert(); //Console.WriteLine(); ...
x