"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" 例外。發現的不可達物件數目
   會被回傳。

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

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

gc.set_debug(flags)

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

gc.get_debug()

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

gc.get_objects(generation=None)

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

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

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

gc.get_stats()

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

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

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

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

   在 3.4 版被加入.

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

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

   The GC classifies objects into three generations depending on how
   many collection sweeps they have survived.  New objects are placed
   in the youngest generation (generation "0").  If an object survives
   a collection it is moved into the next older generation.  Since
   generation "2" is the oldest generation, objects in that generation
   remain there after a collection.  In order to decide when to run,
   the collector keeps track of the number object allocations and
   deallocations since the last collection.  When the number of
   allocations minus the number of deallocations exceeds *threshold0*,
   collection starts.  Initially only generation "0" is examined.  If
   generation "0" has been examined more than *threshold1* times since
   generation "1" has been examined, then generation "1" is examined
   as well. With the third generation, things are a bit more
   complicated, see Collecting the oldest generation for more
   information.

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})
      False
      >>> gc.is_tracked({"a": []})
      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"）。
