使對象類型支持循環(huán)垃圾回收?
Python 對循環(huán)引用的垃圾檢測與回收需要“容器”對象類型的支持,此類型的容器對象中可能包含其它容器對象。不保存其它對象的引用的類型,或者只保存原子類型(如數(shù)字或字符串)的引用的類型,不需要顯式提供垃圾回收的支持。
若要創(chuàng)建一個容器類,類型對象的 tp_flags
字段必須包含 Py_TPFLAGS_HAVE_GC
并提供一個 tp_traverse
處理的實現(xiàn)。如果該類型的實例是可變的,還需要實現(xiàn) tp_clear
。
- Py_TPFLAGS_HAVE_GC
設(shè)置了此標(biāo)志位的類型的對象必須符合此處記錄的規(guī)則。為方便起見,下文把這些對象稱為容器對象。
容器類型的構(gòu)造函數(shù)必須符合兩個規(guī)則:
必須使用
PyObject_GC_New()
或PyObject_GC_NewVar()
為這些對象分配內(nèi)存。初始化了所有可能包含其他容器的引用的字段后,它必須調(diào)用
PyObject_GC_Track()
。
同樣的,對象的釋放器必須符合兩個類似的規(guī)則:
在引用其它容器的字段失效前,必須調(diào)用
PyObject_GC_UnTrack()
。必須使用
PyObject_GC_Del()
釋放對象的內(nèi)存。警告
如果一個類型添加了 Py_TPFLAGS_HAVE_GC,則它 必須 實現(xiàn)至少一個
tp_traverse
句柄或顯式地使用來自其一個或多個子類的句柄。當(dāng)調(diào)用
PyType_Ready()
或者 API 中某些間接調(diào)用它的函數(shù)例如PyType_FromSpecWithBases()
或PyType_FromSpec()
時解釋器就自動填充tp_flags
,tp_traverse
和tp_clear
字段,如果該類型是繼承自實現(xiàn)了垃圾回收器協(xié)議的類并且該子類 沒有 包括Py_TPFLAGS_HAVE_GC
旗標(biāo)的話。
-
TYPE *PyObject_GC_New(TYPE, PyTypeObject *type)?
類似于
PyObject_New()
,適用于設(shè)置了Py_TPFLAGS_HAVE_GC
標(biāo)簽的容器對象。
-
TYPE *PyObject_GC_NewVar(TYPE, PyTypeObject *type, Py_ssize_t size)?
類似于
PyObject_NewVar()
,適用于設(shè)置了Py_TPFLAGS_HAVE_GC
標(biāo)簽的容器對象。
-
TYPE *PyObject_GC_Resize(TYPE, PyVarObject *op, Py_ssize_t newsize)?
為
PyObject_NewVar()
所分配對象重新調(diào)整大小。 返回調(diào)整大小后的對象或在失敗時返回NULL
。 op 必須尚未被垃圾回收器追蹤。
-
void PyObject_GC_Track(PyObject *op)?
- Part of the Stable ABI.
把對象 op 加入到垃圾回收器跟蹤的容器對象中。對象在被回收器跟蹤時必須保持有效的,因為回收器可能在任何時候開始運行。在
tp_traverse
處理前的所有字段變?yōu)橛行Ш?,必須調(diào)用此函數(shù),通常在靠近構(gòu)造函數(shù)末尾的位置。
-
int PyObject_IS_GC(PyObject *obj)?
如果對象實現(xiàn)了垃圾回收器協(xié)議則返回非零值,否則返回 0。
如果此函數(shù)返回 0 則對象無法被垃圾回收器追蹤。
-
int PyObject_GC_IsTracked(PyObject *op)?
- Part of the Stable ABI since version 3.9.
如果 op 對象的類型實現(xiàn)了 GC 協(xié)議且 op 目前正被垃圾回收器追蹤則返回 1, 否則返回 0。
這類似于 Python 函數(shù)
gc.is_tracked()
。3.9 新版功能.
-
int PyObject_GC_IsFinalized(PyObject *op)?
- Part of the Stable ABI since version 3.9.
如果 op 對象的類型實現(xiàn)了 GC 協(xié)議且 op 已經(jīng)被垃圾回收器終結(jié)則返回 1, 否則返回 0。
這類似于 Python 函數(shù)
gc.is_finalized()
。3.9 新版功能.
-
void PyObject_GC_Del(void *op)?
- Part of the Stable ABI.
釋放對象的內(nèi)存,該對象初始化時由
PyObject_GC_New()
或PyObject_GC_NewVar()
分配內(nèi)存。
-
void PyObject_GC_UnTrack(void *op)?
- Part of the Stable ABI.
從回收器跟蹤的容器對象集合中移除 op 對象。 請注意可以在此對象上再次調(diào)用
PyObject_GC_Track()
以將其加回到被跟蹤對象集合。 釋放器 (tp_dealloc
句柄) 應(yīng)當(dāng)在tp_traverse
句柄所使用的任何字段失效之前為對象調(diào)用此函數(shù)。
在 3.8 版更改: _PyObject_GC_TRACK()
和 _PyObject_GC_UNTRACK()
宏已從公有 C API 中移除。
tp_traverse
處理接收以下類型的函數(shù)形參。
-
typedef int (*visitproc)(PyObject *object, void *arg)?
- Part of the Stable ABI.
傳給
tp_traverse
處理的訪問函數(shù)的類型。object 是容器中需要被遍歷的一個對象,第三個形參對應(yīng)于tp_traverse
處理的 arg 。Python核心使用多個訪問者函數(shù)實現(xiàn)循環(huán)引用的垃圾檢測,不需要用戶自行實現(xiàn)訪問者函數(shù)。
tp_traverse
處理必須是以下類型:
-
typedef int (*traverseproc)(PyObject *self, visitproc visit, void *arg)?
- Part of the Stable ABI.
用于容器對象的遍歷函數(shù)。 它的實現(xiàn)必須對 self 所直接包含的每個對象調(diào)用 visit 函數(shù),visit 的形參為所包含對象和傳給處理程序的 arg 值。 visit 函數(shù)調(diào)用不可附帶
NULL
對象作為參數(shù)。 如果 visit 返回非零值,則該值應(yīng)當(dāng)被立即返回。
為了簡化 tp_traverse
處理的實現(xiàn),Python提供了一個 Py_VISIT()
宏。若要使用這個宏,必須把 tp_traverse
的參數(shù)命名為 visit 和 arg 。
-
void Py_VISIT(PyObject *o)?
如果 o 不為
NULL
,則調(diào)用 visit 回調(diào)函數(shù),附帶參數(shù) o 和 arg。 如果 visit 返回一個非零值,則返回該值。 使用此宏之后,tp_traverse
處理程序的形式如下:static int my_traverse(Noddy *self, visitproc visit, void *arg) { Py_VISIT(self->foo); Py_VISIT(self->bar); return 0; }
tp_clear
處理程序必須為 inquiry
類型,如果對象不可變則為 NULL
。
-
typedef int (*inquiry)(PyObject *self)?
- Part of the Stable ABI.
丟棄產(chǎn)生循環(huán)引用的引用。不可變對象不需要聲明此方法,因為他們不可能直接產(chǎn)生循環(huán)引用。需要注意的是,對象在調(diào)用此方法后必須仍是有效的(不能對引用只調(diào)用
Py_DECREF()
方法)。當(dāng)垃圾回收器檢測到該對象在循環(huán)引用中時,此方法會被調(diào)用。
控制垃圾回收器狀態(tài)?
這個 C-API 提供了以下函數(shù)用于控制垃圾回收的運行。
-
Py_ssize_t PyGC_Collect(void)?
- Part of the Stable ABI.
執(zhí)行完全的垃圾回收,如果垃圾回收器已啟用的話。 (請注意
gc.collect()
會無條件地執(zhí)行它。)返回已回收的 + 無法回收的不可獲取對象的數(shù)量。 如果垃圾回收器被禁用或已在執(zhí)行回收,則立即返回
0
。 在垃圾回收期間發(fā)生的錯誤會被傳給sys.unraisablehook
。 此函數(shù)不會引發(fā)異常。
-
int PyGC_Enable(void)?
- Part of the Stable ABI since version 3.10.
啟用垃圾回收器:類似于
gc.enable()
。 返回之前的狀態(tài),0 為禁用而 1 為啟用。3.10 新版功能.
-
int PyGC_Disable(void)?
- Part of the Stable ABI since version 3.10.
禁用垃圾回收器:類似于
gc.disable()
。 返回之前的狀態(tài),0 為禁用而 1 為啟用。3.10 新版功能.
-
int PyGC_IsEnabled(void)?
- Part of the Stable ABI since version 3.10.
查詢垃圾回收器的狀態(tài):類似于
gc.isenabled()
。 返回當(dāng)前的狀態(tài),0 為禁用而 1 為啟用。3.10 新版功能.