python中的記憶體分配與記憶體管理

  • 2019 年 11 月 20 日
  • 筆記

記憶體分配

與你想像中不同的,尤其是從c轉過來的程式設計師,python是一門動態類型的語言,其對象與引用是分離的,與java相似。 每創建一個對象,都會把該對象存儲起來,並把引用返回。

id()

返回記憶體地址

a = 1  id(a)  hex(id(a))

返回對象的引用計數 getrefcount

需要注意的是,當使用某個引用作為參數,傳遞給getrefcount()時,參數實際上創建了一個臨時的引用。因此,getrefcount()所得到的結果,會比期望的多1。

from sys import getrefcount    a = [1, 2, 3]  print(getrefcount(a))    b = a  print(getrefcount(b))

刪除某引用

a = 1  del a

垃圾回收機制

垃圾回收機制是按閾值啟動的,這個閾值可以通過以下程式碼查看

import gc  gc.get_threshold()

返回一個元組(700,10,10), 表明閾值為700

對象的分代(generation)掃描機制

剛剛創建的對象式是0代,每次垃圾回收機制啟動,都會對0代對象掃描。

如果0代對象經歷掃描而存活,會被歸類為1代。類似的,1代對象會被歸類為2代。

如果0代經過一定次數的垃圾回收,啟動對0代和1代的掃描。

如果1代也經歷了一定次數的垃圾回收,啟動對0, 1, 2的掃描。

引用環

引用環指的是對象之間的相互引用。如下程式碼可以產生引用環。

a = []  b = [a]  a.append(b)    del a  del b

Python會複製每個對象的引用計數,比如有兩個相互引用的對象a和b,此時a的引用計數我們用gc_ref_a 來表示,同理用gc_ref_b 來表示b的引用計數,然後Python會遍歷所有的引用對象,這裡只有a和b,遍歷到a的時候,a指向b,將 b的gc_ref_b的值減1,同理遍歷b的時候將a的gc_ref_a的值減1,結果他們的值都為0,最後將不為0的對象保留,為0 的對象進行垃圾回收。