"gc" --- 垃圾回收器介面 (Garbage Collector interface)
*****************************************************

======================================================================

此 module（模組）提供可選的垃圾回收器介面，提供的功能包括：關閉回收器
、調整回收頻率、設定除錯選項。它同時提供對回收器有找到但是無法釋放的不
可達物件 (unreachable object) 的存取。由於 Python 使用了帶有參照計數的
回收器，如果你確定你的程式不會產生參照迴圈 (reference cycle)，你可以關
閉回收器。可以透過呼叫 "gc.disable()" 關閉自動垃圾回收。若要為一個存在
記憶體流失的程式 (leaking program) 除錯，請呼叫
"gc.set_debug(gc.DEBUG_LEAK)"；需要注意的是，它包含 "gc.DEBUG_SAVEALL"
，使得被回收的物件會被存放在 gc.garbage 中以待檢查。

"gc" module 提供下列函式：

gc.enable()

   啟用自動垃圾回收。

gc.disable()

   停用自動垃圾回收。

gc.isenabled()

   如果啟用了自動回收則回傳 "True"。

gc.collect(generation=2)

   啟動垃圾回收。可選的引數 *generation* 可以是一個指明需要回收哪一代
   垃圾的整數（從 0 到 2）。當 generation 數值無效時，會引發
   "ValueError" 例外。可回收物件與不可回收物件的總和會被回傳。

   呼叫 "gc.collect(0)" 將對年輕代執行 GC 回收。

   呼叫 "gc.collect(1)" 將對年輕代執行 GC 回收並對年老代執行增量回收。

   呼叫 "gc.collect(2)" 或 "gc.collect()" 執行完整回收

   每當執行完整回收或最高代 (2) 回收時，為多個內建型別所維護的空閒列表
   會被清空。為了特定型別的實現，特別是 "float"，在某些空閒列表中並非
   所有項目都會被釋放。

   當直譯器已經執行收集時呼叫 "gc.collect()" 的效果是未定義的。

   在 3.14 版的變更: "generation=1" 會執行增量收集。

gc.set_debug(flags)

   設定垃圾回收器的除錯旗標。除錯資訊會被寫入 "sys.stderr"。請見下方的
   除錯旗標列表，可以使用位元操作 (bit operation) 進行設定以控制除錯程
   式。

gc.get_debug()

   回傳目前設置的除錯旗標。

gc.get_objects(generation=None)

   回傳一個包含回收器正在追蹤的所有物件的 list，除去所回傳的 list。如
   果 *generation* 不為 "None"，只回傳以下物件。

   * 0: 年輕代中的所有物件。

   * 1: 沒有物件，因為不存在第一代（截至 Python 3.14）

   * 2: 年老代中的所有物件。

   在 3.8 版的變更: 新增 *generation* 參數。

   在 3.14 版的變更: 第一代已被刪除

   引發一個附帶引數 "generation" 的稽核事件 (auditing event)
   "gc.get_objects"。

gc.get_stats()

   回傳一個包含三個字典物件的 list，每個字典分別包含對應代中自從直譯器
   開始執行後的垃圾回收統計資料。字典的鍵的數目在將來可能會改變，但目
   前每個字典包含以下項目：

   * "collections" 是該代被回收的次數；

   * "collected" 是該代中被回收的物件總數；

   * "uncollectable" 是在這一代中被發現無法回收的物件總數（因此被移到
     "garbage" list 中）。

   在 3.4 版被加入.

gc.set_threshold(threshold0[, threshold1[, threshold2]])

   設定垃圾回收閾值（回收頻率）。 將 *threshold0* 設為零會停止回收。

   GC 根據物件是否在回收中倖存下來而將其分為兩代。新的物件會被放置在年
   輕代中。如果一個物件在回收中倖存下來，它將被移動到年老代中。

   為了決定何時運行，回收器會追蹤自上次回收以來物件分配和釋放的數量。
   當分配數量減去釋放數量超過 *threshold0* 時，回收就會開始。每次回收
   都會去回收年輕代中的所有物件和年老代的部分物件。

   在自由執行緒建置 (free-threaded build) 中，在運行回收器之前還會檢查
   行程記憶體使用量的增加。如果自上次回收以來記憶體使用量未增加 10%，
   且物件分配的淨數量未超過 *threshold0* 的 40 倍，則不會運行回收。

   年老代中被回收的物件比例與 *threshold1* 成**反比**。*threshold1* 越
   大，年老代中物件的回收就越慢。以預設值 10 來說，每次回收時會掃描年
   老代中的 1%。

   *threshold2* 會被忽略。

   有關更多資訊，請參閱垃圾回收器設計。

   在 3.14 版的變更: *threshold2* 會被忽略

gc.get_count()

   將目前回收計數以 "(count0, count1, count2)" 形式的 tuple 回傳。

gc.get_threshold()

   將目前回收閾值以 "(threshold0, threshold1, threshold2)" 形式的
   tuple 回傳。

gc.get_referrers(*objs)

   回傳包含直接參照 objs 中任一個物件的物件 list。這個函式只定位支援垃
   圾回收的容器；參照了其它物件但不支援垃圾回收的擴充套件型別無法被找
   到。

   需要注意的是，已經解除參照的物件，但仍存在於參照迴圈中未被回收時，
   該物件仍然會被作為參照者出現在回傳的 list 中。若只要取得目前正在參
   照的物件，需要在呼叫 "get_referrers()" 之前呼叫 "collect()"。

   警告:

     在使用 "get_referrers()" 回傳的物件時必須要小心，因為其中的一些物
     件可能仍在建構中而處於暫時無效的狀態。不要把 "get_referrers()" 用
     於除錯以外的其它目的。

   引發一個附帶引數 "objs" 的稽核事件 "gc.get_referrers"。

gc.get_referents(*objs)

   回傳包含被任意一個引數直接參照之物件的 list。回傳的被參照物件是有被
   引數的 C 語言級別 "tp_traverse" 方法（若存在）瀏覽到的物件，可能不
   是所有的實際直接可達物件。只有支援垃圾回收的物件支援 "tp_traverse"
   方法，並且此方法只會瀏覽涉及參照迴圈的物件。因此，可以有以下例子：
   一個整數對於一個引數是直接可達的，這個整數物件有可能出現或不出現在
   結果的 list 當中。

   引發一個附帶引數 "objs" 的稽核事件 "gc.get_referents"。

gc.is_tracked(obj)

   當物件正在被垃圾回收器追蹤時回傳 "True"，否則回傳 "False"。一般來說
   ，原子型別 (atomic type) 的實例不會被追蹤，而非原子型別（如容器、使
   用者自己定義的物件）會被追蹤。然而，有一些特定型別最佳化會被用來減
   少垃圾回收器在簡單實例（如只含有原子性的鍵和值的字典）上的足跡：

      >>> gc.is_tracked(0)
      False
      >>> gc.is_tracked("a")
      False
      >>> gc.is_tracked([])
      True
      >>> gc.is_tracked({})
      False
      >>> gc.is_tracked({"a": 1})
      True

   在 3.1 版被加入.

gc.is_finalized(obj)

   如果給定物件已被垃圾回收器終結則回傳 "True"，否則回傳 "False"。：

      >>> x = None
      >>> class Lazarus:
      ...     def __del__(self):
      ...         global x
      ...         x = self
      ...
      >>> lazarus = Lazarus()
      >>> gc.is_finalized(lazarus)
      False
      >>> del lazarus
      >>> gc.is_finalized(x)
      True

   在 3.9 版被加入.

gc.freeze()

   凍結 (freeze) 垃圾回收器所追蹤的所有物件；將它們移至永久代並忽略所
   有未來的收集動作。

   如果一個行程將在沒有 "exec()" 的情況下進行 "fork()"，避免子行程中不
   必要的寫入時複製將最大化記憶體共享並減少整體記憶體使用。這需要避免
   在父行程的記憶體頁面中建立已釋放的「漏洞」，並確保子行程中的 GC 收
   集不會觸及源自父行程的長壽命物件的 "gc_refs" 計數器。要實現這兩個目
   標，請在父行程的早期呼叫 "gc.disable()"，在 "fork()" 之前呼叫
   "gc.freeze()"，並儘早在子行程中呼叫 "gc.enable()"。

   在 3.7 版被加入.

gc.unfreeze()

   解凍 (unfreeze) 永久代中的物件，並將它們放回到最年老代中。

   在 3.7 版被加入.

gc.get_freeze_count()

   回傳永久代中的物件數量。

   在 3.7 版被加入.

以下變數僅供唯讀存取（你可以修改其值但不應該重新繫結 (rebind) 它們）：

gc.garbage

   一個回收器發現不可達而又無法被釋放的物件（不可回收物件）list。從
   Python 3.4 開始，該 list 在大多數時候都應該是空的，除非使用了有非
   "NULL" "tp_del" 槽位的 C 擴充套件型別的實例。

   如果設定了 "DEBUG_SAVEALL"，則所有不可達物件將被加進該 list 而不會
   被釋放。

   在 3.2 版的變更: 當 *interpreter shutdown* 即直譯器關閉時，若此
   list 非空，會產生 "ResourceWarning"，在預設情況下此警告不會被提醒。
   如果設定了 "DEBUG_UNCOLLECTABLE"，所有無法被回收的物件會被印出。

   在 3.4 版的變更: 根據 **PEP 442**，帶有 "__del__()" method 的物件最
   終不會在 "gc.garbage" 內。

gc.callbacks

   會被垃圾回收器在回收開始前和完成後叫用的一系列回呼函式 (callback)
   。這些回呼函式在被呼叫時附帶兩個引數：*phase* 和 *info*。

   *phase* 可為以下兩者之一：

      "start"：垃圾回收即將開始。

      "stop"：垃圾回收已結束。

   *info* 是一個字典，提供回呼函式更多資訊。已有定義的鍵有：

      "generation"（代）：正在被回收的最年老的一代。

      "collected"（已回收的）：當 *phase* 為 "stop" 時，被成功回收的物
      件的數目。

      "uncollectable"（不可回收的）：當 *phase* 為 "stop" 時，不能被回
      收並被放入 "garbage" 的物件的數目。

   應用程式可以把他們自己的回呼函式加入此 list。主要的使用場景有：

      收集垃圾回收的統計資料，如：不同代的回收頻率、回收任務所花費的時
      間。

      讓應用程式可以識別和清理他們自己在 "garbage" 中的不可回收型別物
      件。

   在 3.3 版被加入.

以下常數是為了和 "set_debug()" 一起使用所提供：

gc.DEBUG_STATS

   在回收完成後印出統計資訊。當調校回收頻率設定時，這些資訊會很有用。

gc.DEBUG_COLLECTABLE

   當發現可回收物件時印出資訊。

gc.DEBUG_UNCOLLECTABLE

   印出找到的不可回收物件的資訊（指不能被回收器回收的不可達物件）。這
   些物件會被新增到 "garbage" list 中。

   在 3.2 版的變更: 當 *interpreter shutdown*（直譯器關閉）時，若
   "garbage" list 不是空的，那這些內容也會被印出。

gc.DEBUG_SAVEALL

   設定後，所有回收器找到的不可達物件會被加進 *garbage* 而不是直接被釋
   放。這在為一個記憶體流失的程式除錯時會很有用。

gc.DEBUG_LEAK

   要印出記憶體流失程式之相關資訊時，回收器所需的除錯旗標。（等同於
   "DEBUG_COLLECTABLE | DEBUG_UNCOLLECTABLE | DEBUG_SAVEALL"）。
