通用物件結構

在 Python 物件型別的定義中使用了大量的結構。本節描述了這些結構及其用法。

基本物件型別和宏

所有 Python 物件最終在物件記憶體表示的開頭共享少量欄位。這些欄位由 PyObjectPyVarObject 型別表示,而這些型別又由一些宏的擴充套件定義,這些宏直接或間接用於所有其他 Python 物件的定義。更多宏可在引用計數中找到。

型別 PyObject
有限 API 的一部分。(只有某些成員是穩定 ABI 的一部分。)

所有物件型別都是此型別的擴充套件。此型別包含 Python 將指向物件的指標視為物件所需的資訊。在正常的“釋出”構建中,它只包含物件的引用計數和指向相應型別物件的指標。實際上沒有東西被宣告為 PyObject,但指向 Python 物件的每個指標都可以轉換為 PyObject*

成員不得直接訪問;應使用 Py_REFCNTPy_TYPE 等宏。

Py_ssize_t ob_refcnt
作為 穩定 ABI 的一部分。

物件的引用計數,由 Py_REFCNT 返回。不要直接使用此欄位;應使用函式和宏,例如 Py_REFCNTPy_INCREF()Py_DecRef()

欄位型別可能與 Py_ssize_t 不同,具體取決於構建配置和平臺。

PyTypeObject *ob_type
作為 穩定 ABI 的一部分。

物件的型別。不要直接使用此欄位;應使用 Py_TYPEPy_SET_TYPE()

型別 PyVarObject
有限 API 的一部分。(只有某些成員是穩定 ABI 的一部分。)

這是 PyObject 的擴充套件,它增加了 ob_size 欄位。它用於具有某種“長度”概念的物件。

PyObject 一樣,成員不得直接訪問;應使用 Py_SIZEPy_REFCNTPy_TYPE 等宏。

Py_ssize_t ob_size
作為 穩定 ABI 的一部分。

一個大小欄位,其內容應被視為物件的內部實現細節。

不要直接使用此欄位;應使用 Py_SIZE

物件建立函式,例如 PyObject_NewVar(),通常會將此欄位設定為請求的大小(專案數)。建立後,可以使用 Py_SET_SIZE 將任意值儲存到 ob_size 中。

要獲取物件的公共公開長度(由 Python 函式 len() 返回),應使用 PyObject_Length()

PyObject_HEAD

這是一個在宣告不具有可變長度的新物件型別時使用的宏。PyObject_HEAD 宏擴充套件為

PyObject ob_base;

請參閱上面 PyObject 的文件。

PyObject_VAR_HEAD

這是一個在宣告具有可變長度的新物件型別時使用的宏。PyObject_VAR_HEAD 宏擴充套件為

PyVarObject ob_base;

請參閱上面 PyVarObject 的文件。

PyTypeObject PyBaseObject_Type
作為 穩定 ABI 的一部分。

所有其他物件的基類,與 Python 中的 object 相同。

int Py_Is(PyObject *x, PyObject *y)
自 3.10 版本以來,作為 穩定 ABI 的一部分。

測試物件 *x* 是否是物件 *y*,與 Python 中的 x is y 相同。

在 3.10 版本加入。

int Py_IsNone(PyObject *x)
自 3.10 版本以來,作為 穩定 ABI 的一部分。

測試物件是否是 None 單例,與 Python 中的 x is None 相同。

在 3.10 版本加入。

int Py_IsTrue(PyObject *x)
自 3.10 版本以來,作為 穩定 ABI 的一部分。

測試物件是否是 True 單例,與 Python 中的 x is True 相同。

在 3.10 版本加入。

int Py_IsFalse(PyObject *x)
自 3.10 版本以來,作為 穩定 ABI 的一部分。

測試物件是否是 False 單例,與 Python 中的 x is False 相同。

在 3.10 版本加入。

PyTypeObject *Py_TYPE(PyObject *o)
返回值:借用引用。自版本 3.14 起成為穩定 ABI 的一部分。

獲取 Python 物件 *o* 的型別。

返回的引用是從 *o* 借用的。不要使用 Py_DECREF() 或類似函式釋放它。

版本 3.11 中已更改: Py_TYPE() 已更改為內聯靜態函式。引數型別不再是 const PyObject*

int Py_IS_TYPE(PyObject *o, PyTypeObject *type)

如果物件 *o* 的型別是 *type*,則返回非零值。否則返回零。等效於:Py_TYPE(o) == type

在 3.9 版本中新增。

void Py_SET_TYPE(PyObject *o, PyTypeObject *type)

將物件 *o* 的型別設定為 *type*,不進行任何檢查或引用計數。

這是一個非常低階的操作。考慮改用 PyObject_SetAttrString() 或類似函式設定 Python 屬性 __class__

請注意,分配不相容的型別可能導致未定義行為。

如果 *type* 是堆型別,則呼叫者必須建立對其的新引用。類似地,如果 *o* 的舊型別是堆型別,則呼叫者必須釋放對該型別的引用。

在 3.9 版本中新增。

Py_ssize_t Py_SIZE(PyVarObject *o)

獲取 *o* 的 ob_size 欄位。

版本 3.11 中已更改: Py_SIZE() 已更改為內聯靜態函式。引數型別不再是 const PyVarObject*

void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size)

將 *o* 的 ob_size 欄位設定為 *size*。

在 3.9 版本中新增。

PyObject_HEAD_INIT(type)

這是一個宏,它擴充套件為新 PyObject 型別的初始化值。此宏擴充套件為

_PyObject_EXTRA_INIT
1, type,
PyVarObject_HEAD_INIT(type, size)

這是一個宏,它擴充套件為新 PyVarObject 型別的初始化值,包括 ob_size 欄位。此宏擴充套件為

_PyObject_EXTRA_INIT
1, type, size,

實現函式和方法

型別 PyCFunction
作為 穩定 ABI 的一部分。

用於在 C 中實現大多數 Python 可呼叫物件的函式型別。此型別的函式接受兩個 PyObject* 引數並返回一個此類值。如果返回值為 NULL,則應已設定異常。如果不是 NULL,則返回值被解釋為函式在 Python 中公開的返回值。函式必須返回一個新的引用。

函式簽名是

PyObject *PyCFunction(PyObject *self,
                      PyObject *args);
型別 PyCFunctionWithKeywords
作為 穩定 ABI 的一部分。

用於在 C 中實現具有簽名 METH_VARARGS | METH_KEYWORDS 的 Python 可呼叫物件的函式型別。函式簽名是

PyObject *PyCFunctionWithKeywords(PyObject *self,
                                  PyObject *args,
                                  PyObject *kwargs);
型別 PyCFunctionFast
自 3.13 版本起成為 穩定 ABI 的一部分。

用於在 C 中實現具有簽名 METH_FASTCALL 的 Python 可呼叫物件的函式型別。函式簽名是

PyObject *PyCFunctionFast(PyObject *self,
                          PyObject *const *args,
                          Py_ssize_t nargs);
型別 PyCFunctionFastWithKeywords
自 3.13 版本起成為 穩定 ABI 的一部分。

用於在 C 中實現具有簽名 METH_FASTCALL | METH_KEYWORDS 的 Python 可呼叫物件的函式型別。函式簽名是

PyObject *PyCFunctionFastWithKeywords(PyObject *self,
                                      PyObject *const *args,
                                      Py_ssize_t nargs,
                                      PyObject *kwnames);
型別 PyCMethod

用於在 C 中實現具有簽名 METH_METHOD | METH_FASTCALL | METH_KEYWORDS 的 Python 可呼叫物件的函式型別。函式簽名是

PyObject *PyCMethod(PyObject *self,
                    PyTypeObject *defining_class,
                    PyObject *const *args,
                    Py_ssize_t nargs,
                    PyObject *kwnames)

在 3.9 版本中新增。

型別 PyMethodDef
穩定 ABI 的一部分(包括所有成員)。

用於描述擴充套件型別方法的結構。此結構有四個欄位

const char *ml_name

方法的名稱。

PyCFunction ml_meth

指向 C 實現的指標。

int ml_flags

指示如何構造呼叫的標誌位。

const char *ml_doc

指向文件字串內容的指標。

ml_meth 是一個 C 函式指標。這些函式可以是不同型別,但它們總是返回 PyObject*。如果函式不是 PyCFunction 型別,編譯器將在方法表中需要一個強制型別轉換。即使 PyCFunction 將第一個引數定義為 PyObject*,方法實現通常使用 *self* 物件的特定 C 型別。

ml_flags 欄位是一個位域,可以包含以下標誌。各個標誌指示呼叫約定或繫結約定。

有這些呼叫約定

METH_VARARGS

這是典型的呼叫約定,其中方法具有 PyCFunction 型別。函式期望兩個 PyObject* 值。第一個是方法的 *self* 物件;對於模組函式,它是模組物件。第二個引數(通常稱為 *args*)是一個表示所有引數的元組物件。此引數通常使用 PyArg_ParseTuple()PyArg_UnpackTuple() 處理。

METH_KEYWORDS

只能與其他標誌的某些組合一起使用:METH_VARARGS | METH_KEYWORDSMETH_FASTCALL | METH_KEYWORDSMETH_METHOD | METH_FASTCALL | METH_KEYWORDS

METH_VARARGS | METH_KEYWORDS

帶有這些標誌的方法必須是 PyCFunctionWithKeywords 型別。函式期望三個引數:*self*、*args*、*kwargs*,其中 *kwargs* 是所有關鍵字引數的字典,如果沒有關鍵字引數,則可能為 NULL。引數通常使用 PyArg_ParseTupleAndKeywords() 處理。

METH_FASTCALL

只支援位置引數的快速呼叫約定。方法具有 PyCFunctionFast 型別。第一個引數是 *self*,第二個引數是 PyObject* 值的 C 陣列,指示引數,第三個引數是引數的數量(陣列的長度)。

在 3.7 版本加入。

版本 3.10 中已更改: METH_FASTCALL 現在是 穩定 ABI 的一部分。

METH_FASTCALL | METH_KEYWORDS

METH_FASTCALL 的擴充套件,也支援關鍵字引數,方法型別為 PyCFunctionFastWithKeywords。關鍵字引數的傳遞方式與 vectorcall 協議相同:有一個額外的第四個 PyObject* 引數,它是一個表示關鍵字引數名稱的元組(保證是字串),如果沒有關鍵字,則可能為 NULL。關鍵字引數的值儲存在 *args* 陣列中,位於位置引數之後。

在 3.7 版本加入。

METH_METHOD

只能與其他標誌的組合一起使用:METH_METHOD | METH_FASTCALL | METH_KEYWORDS

METH_METHOD | METH_FASTCALL | METH_KEYWORDS

METH_FASTCALL | METH_KEYWORDS 的擴充套件,支援*定義類*,即包含該方法的類。定義類可能是 Py_TYPE(self) 的超類。

方法必須是 PyCMethod 型別,與 METH_FASTCALL | METH_KEYWORDS 相同,但 defining_class 引數在 self 之後新增。

在 3.9 版本中新增。

METH_NOARGS

不帶引數的方法如果使用 METH_NOARGS 標誌列出,則無需檢查是否提供了引數。它們需要是 PyCFunction 型別。第一個引數通常命名為 *self*,將持有對模組或物件例項的引用。在所有情況下,第二個引數都將為 NULL

函式必須有兩個引數。由於第二個引數未使用,可以使用 Py_UNUSED 來防止編譯器警告。

METH_O

帶單個物件引數的方法可以使用 METH_O 標誌列出,而不是呼叫帶 "O" 引數的 PyArg_ParseTuple()。它們具有 PyCFunction 型別,帶 *self* 引數,以及一個表示單個引數的 PyObject* 引數。

這兩個常量不用於指示呼叫約定,而是在與類方法一起使用時指示繫結。它們不能用於為模組定義的函式。對於任何給定的方法,最多可以設定其中一個標誌。

METH_CLASS

方法將把型別物件作為第一個引數而不是型別例項。這用於建立*類方法*,類似於使用 classmethod() 內建函式建立的方法。

METH_STATIC

方法將把 NULL 作為第一個引數而不是型別例項。這用於建立*靜態方法*,類似於使用 staticmethod() 內建函式建立的方法。

另一個常量控制方法是否替換具有相同方法名稱的另一個定義。

METH_COEXIST

該方法將取代現有定義。如果沒有 *METH_COEXIST*,預設是跳過重複定義。由於槽包裝器在方法表之前載入,例如,存在 *sq_contains* 槽將生成一個名為 __contains__() 的包裝方法,並阻止載入具有相同名稱的相應 PyCFunction。如果定義了此標誌,PyCFunction 將取代包裝物件載入並與槽共存。這很有幫助,因為對 PyCFunction 的呼叫比包裝物件呼叫更最佳化。

PyObject *PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *cls)
返回值:新引用。自版本 3.9 起成為穩定 ABI 的一部分。

將 *ml* 轉換為 Python 可呼叫物件。呼叫者必須確保 *ml* 的生命週期長於可呼叫物件。通常,*ml* 被定義為靜態變數。

當被呼叫時,*self* 引數將作為 *self* 引數傳遞給 ml->ml_meth 中的 C 函式。*self* 可以是 NULL

可呼叫物件的 __module__ 屬性可以從給定的 *module* 引數設定。*module* 應該是一個 Python 字串,它將用作函式定義的模組的名稱。如果不可用,可以將其設定為 NoneNULL

*cls* 引數將作為 *defining_class* 引數傳遞給 C 函式。如果 ml->ml_flags 上設定了 METH_METHOD,則必須設定它。

在 3.9 版本中新增。

PyObject *PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
返回值: 新引用。 穩定ABI 的一部分。

等同於 PyCMethod_New(ml, self, module, NULL)

PyObject *PyCFunction_New(PyMethodDef *ml, PyObject *self)
返回值:新引用。自版本 3.4 起成為穩定 ABI 的一部分。

等同於 PyCMethod_New(ml, self, NULL, NULL)

訪問擴充套件型別的屬性

型別 PyMemberDef
穩定 ABI 的一部分(包括所有成員)。

描述與 C 結構成員對應的型別屬性的結構。定義類時,將這些結構的以 NULL 終止的陣列放入 tp_members 槽中。

其欄位依次是

const char *name

成員的名稱。NULL 值標記 PyMemberDef[] 陣列的結束。

字串應該是靜態的,不會複製它。

int type

C 結構中成員的型別。有關可能的值,請參閱成員型別

Py_ssize_t offset

成員在型別物件結構中的位元組偏移量。

int flags

零個或多個成員標誌,使用位或組合。

const char *doc

文件字串,或 NULL。字串應該是靜態的,不會複製它。通常使用 PyDoc_STR 定義。

預設情況下(當 flags0 時),成員允許讀寫訪問。對於只讀訪問,請使用 Py_READONLY 標誌。某些型別,例如 Py_T_STRING,隱含 Py_READONLY。只有 Py_T_OBJECT_EX(和舊版 T_OBJECT)成員可以刪除。

對於堆分配的型別(使用 PyType_FromSpec() 或類似函式建立),PyMemberDef 可能包含特殊成員 "__vectorcalloffset__" 的定義,對應於型別物件中的 tp_vectorcall_offset。此成員必須定義為 Py_T_PYSSIZET,並且可以是 Py_READONLYPy_READONLY | Py_RELATIVE_OFFSET。例如

static PyMemberDef spam_type_members[] = {
    {"__vectorcalloffset__", Py_T_PYSSIZET,
     offsetof(Spam_object, vectorcall), Py_READONLY},
    {NULL}  /* Sentinel */
};

(您可能需要 #include <stddef.h> 才能使用 offsetof()。)

舊版偏移量 tp_dictoffsettp_weaklistoffset 可以透過使用 "__dictoffset__""__weaklistoffset__" 成員類似地定義,但強烈建議擴充套件使用 Py_TPFLAGS_MANAGED_DICTPy_TPFLAGS_MANAGED_WEAKREF

版本 3.12 中已更改: PyMemberDef 始終可用。以前,它需要包含 "structmember.h"

版本 3.14 中已更改: Py_RELATIVE_OFFSET 現在允許用於 "__vectorcalloffset__""__dictoffset__""__weaklistoffset__"

PyObject *PyMember_GetOne(const char *obj_addr, struct PyMemberDef *m)
作為 穩定 ABI 的一部分。

獲取地址為 *obj_addr* 的物件所擁有的屬性。該屬性由 PyMemberDef *m* 描述。錯誤時返回 NULL

版本 3.12 中已更改: PyMember_GetOne 始終可用。以前,它需要包含 "structmember.h"

int PyMember_SetOne(char *obj_addr, struct PyMemberDef *m, PyObject *o)
作為 穩定 ABI 的一部分。

將地址為 *obj_addr* 的物件所擁有的屬性設定為物件 *o*。要設定的屬性由 PyMemberDef *m* 描述。成功時返回 0,失敗時返回負值。

版本 3.12 中已更改: PyMember_SetOne 始終可用。以前,它需要包含 "structmember.h"

成員標誌

以下標誌可與 PyMemberDef.flags 一起使用

Py_READONLY

不可寫入。

Py_AUDIT_READ

讀取前發出 object.__getattr__ 審計事件

Py_RELATIVE_OFFSET

指示此 PyMemberDef 條目的 offset 指示從子類特定資料而非從 PyObject 的偏移量。

只能作為 Py_tp_members slot 的一部分使用,當使用負 basicsize 建立類時。在這種情況下它是強制性的。

此標誌僅在 PyType_Slot 中使用。在類建立期間設定 tp_members 時,Python 會清除它並將 PyMemberDef.offset 設定為從 PyObject 結構的偏移量。

版本 3.10 中已更改: RESTRICTEDREAD_RESTRICTEDWRITE_RESTRICTED 宏(可透過 #include "structmember.h" 獲得)已棄用。READ_RESTRICTEDRESTRICTED 等同於 Py_AUDIT_READWRITE_RESTRICTED 無任何作用。

版本 3.12 中已更改: READONLY 宏已重新命名為 Py_READONLYPY_AUDIT_READ 宏已使用 Py_ 字首重新命名。新名稱現在始終可用。以前,這些需要 #include "structmember.h"。該標頭檔案仍然可用並提供舊名稱。

成員型別

PyMemberDef.type 可以是以下宏之一,對應於各種 C 型別。當在 Python 中訪問成員時,它將被轉換為等效的 Python 型別。當從 Python 設定時,它將被轉換回 C 型別。如果無法實現,則會引發異常,例如 TypeErrorValueError

除非標記為 (D),否則以此方式定義的屬性不能使用例如 deldelattr() 刪除。

宏名稱

C 型別

Python 型別

Py_T_BYTE

char

int

Py_T_SHORT

short

int

Py_T_INT

int

int

Py_T_LONG

long

int

Py_T_LONGLONG

long long

int

Py_T_UBYTE

unsigned char

int

Py_T_UINT

unsigned int

int

Py_T_USHORT

unsigned short

int

Py_T_ULONG

unsigned long

int

Py_T_ULONGLONG

unsigned long long

int

Py_T_PYSSIZET

Py_ssize_t

int

Py_T_FLOAT

浮點數

浮點數

Py_T_DOUBLE

double

浮點數

Py_T_BOOL

char (寫入為 0 或 1)

bool

Py_T_STRING

const char* (*)

str (只讀)

Py_T_STRING_INPLACE

const char[] (*)

str (只讀)

Py_T_CHAR

char (0-127)

str (**)

Py_T_OBJECT_EX

PyObject*

object (D)

(*): 以零終止的 UTF8 編碼 C 字串。對於 Py_T_STRING,C 表示是一個指標;對於 Py_T_STRING_INPLACE,字串直接儲存在結構中。

(**): 長度為 1 的字串。只接受 ASCII。

(RO): 隱含 Py_READONLY

(D): 可以刪除,在這種情況下,指標設定為 NULL。讀取 NULL 指標會引發 AttributeError

版本 3.12 新增: 在以前的版本中,這些宏僅在包含 #include "structmember.h" 時可用,並且名稱沒有 Py_ 字首(例如 T_INT)。該標頭檔案仍然可用,幷包含舊名稱以及以下已棄用型別

T_OBJECT

Py_T_OBJECT_EX 類似,但 NULL 被轉換為 None。這導致 Python 中出現令人驚訝的行為:刪除屬性實際上將其設定為 None

T_NONE

始終為 None。必須與 Py_READONLY 一起使用。

定義獲取器和設定器

型別 PyGetSetDef
穩定 ABI 的一部分(包括所有成員)。

用於為型別定義類似屬性訪問的結構。另請參閱 PyTypeObject.tp_getset 槽的描述。

const char *name

屬性名稱

getter get

用於獲取屬性的 C 函式。

setter set

可選的 C 函式,用於設定或刪除屬性。如果為 NULL,則屬性為只讀。

const char *doc

可選文件字串

void *closure

可選的使用者資料指標,為 getter 和 setter 提供附加資料。

typedef PyObject *(*getter)(PyObject*, void*)
作為 穩定 ABI 的一部分。

get 函式接受一個 PyObject* 引數(例項)和一個使用者資料指標(相關的 closure

成功時應返回新引用,失敗時應返回 NULL 並設定異常。

typedef int (*setter)(PyObject*, PyObject*, void*)
作為 穩定 ABI 的一部分。

set 函式接受兩個 PyObject* 引數(例項和要設定的值)和一個使用者資料指標(相關的 closure

如果屬性應該被刪除,則第二個引數為 NULL。成功時應返回 0,失敗時應返回 -1 並設定異常。