通用物件結構¶
在 Python 物件型別的定義中使用了大量的結構。本節描述了這些結構及其用法。
基本物件型別和宏¶
所有 Python 物件最終在物件記憶體表示的開頭共享少量欄位。這些欄位由 PyObject
和 PyVarObject
型別表示,而這些型別又由一些宏的擴充套件定義,這些宏直接或間接用於所有其他 Python 物件的定義。更多宏可在引用計數中找到。
-
型別 PyObject¶
- 有限 API 的一部分。(只有某些成員是穩定 ABI 的一部分。)
所有物件型別都是此型別的擴充套件。此型別包含 Python 將指向物件的指標視為物件所需的資訊。在正常的“釋出”構建中,它只包含物件的引用計數和指向相應型別物件的指標。實際上沒有東西被宣告為
PyObject
,但指向 Python 物件的每個指標都可以轉換為 PyObject*。成員不得直接訪問;應使用
Py_REFCNT
和Py_TYPE
等宏。-
Py_ssize_t ob_refcnt¶
- 作為 穩定 ABI 的一部分。
物件的引用計數,由
Py_REFCNT
返回。不要直接使用此欄位;應使用函式和宏,例如Py_REFCNT
、Py_INCREF()
和Py_DecRef()
。欄位型別可能與
Py_ssize_t
不同,具體取決於構建配置和平臺。
-
PyTypeObject *ob_type¶
- 作為 穩定 ABI 的一部分。
物件的型別。不要直接使用此欄位;應使用
Py_TYPE
和Py_SET_TYPE()
。
-
Py_ssize_t ob_refcnt¶
-
型別 PyVarObject¶
- 有限 API 的一部分。(只有某些成員是穩定 ABI 的一部分。)
這是
PyObject
的擴充套件,它增加了ob_size
欄位。它用於具有某種“長度”概念的物件。與
PyObject
一樣,成員不得直接訪問;應使用Py_SIZE
、Py_REFCNT
和Py_TYPE
等宏。-
Py_ssize_t ob_size¶
- 作為 穩定 ABI 的一部分。
一個大小欄位,其內容應被視為物件的內部實現細節。
不要直接使用此欄位;應使用
Py_SIZE
。物件建立函式,例如
PyObject_NewVar()
,通常會將此欄位設定為請求的大小(專案數)。建立後,可以使用Py_SET_SIZE
將任意值儲存到ob_size
中。要獲取物件的公共公開長度(由 Python 函式
len()
返回),應使用PyObject_Length()
。
-
Py_ssize_t ob_size¶
-
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()
或類似函式釋放它。
-
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 版本中新增。
-
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¶
指向文件字串內容的指標。
-
const char *ml_name¶
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_KEYWORDS、METH_FASTCALL | METH_KEYWORDS 和 METH_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 字串,它將用作函式定義的模組的名稱。如果不可用,可以將其設定為None
或NULL
。*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[]
陣列的結束。字串應該是靜態的,不會複製它。
-
Py_ssize_t offset¶
成員在型別物件結構中的位元組偏移量。
預設情況下(當
flags
為0
時),成員允許讀寫訪問。對於只讀訪問,請使用Py_READONLY
標誌。某些型別,例如Py_T_STRING
,隱含Py_READONLY
。只有Py_T_OBJECT_EX
(和舊版T_OBJECT
)成員可以刪除。對於堆分配的型別(使用
PyType_FromSpec()
或類似函式建立),PyMemberDef
可能包含特殊成員"__vectorcalloffset__"
的定義,對應於型別物件中的tp_vectorcall_offset
。此成員必須定義為Py_T_PYSSIZET
,並且可以是Py_READONLY
或Py_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_dictoffset
和tp_weaklistoffset
可以透過使用"__dictoffset__"
和"__weaklistoffset__"
成員類似地定義,但強烈建議擴充套件使用Py_TPFLAGS_MANAGED_DICT
和Py_TPFLAGS_MANAGED_WEAKREF
。版本 3.12 中已更改:
PyMemberDef
始終可用。以前,它需要包含"structmember.h"
。版本 3.14 中已更改:
Py_RELATIVE_OFFSET
現在允許用於"__vectorcalloffset__"
、"__dictoffset__"
和"__weaklistoffset__"
。 -
const char *name¶
-
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_RELATIVE_OFFSET¶
指示此
PyMemberDef
條目的offset
指示從子類特定資料而非從PyObject
的偏移量。只能作為
Py_tp_members
slot
的一部分使用,當使用負basicsize
建立類時。在這種情況下它是強制性的。此標誌僅在
PyType_Slot
中使用。在類建立期間設定tp_members
時,Python 會清除它並將PyMemberDef.offset
設定為從PyObject
結構的偏移量。
版本 3.10 中已更改: RESTRICTED
、READ_RESTRICTED
和 WRITE_RESTRICTED
宏(可透過 #include "structmember.h"
獲得)已棄用。READ_RESTRICTED
和 RESTRICTED
等同於 Py_AUDIT_READ
;WRITE_RESTRICTED
無任何作用。
版本 3.12 中已更改: READONLY
宏已重新命名為 Py_READONLY
。PY_AUDIT_READ
宏已使用 Py_
字首重新命名。新名稱現在始終可用。以前,這些需要 #include "structmember.h"
。該標頭檔案仍然可用並提供舊名稱。
成員型別¶
PyMemberDef.type
可以是以下宏之一,對應於各種 C 型別。當在 Python 中訪問成員時,它將被轉換為等效的 Python 型別。當從 Python 設定時,它將被轉換回 C 型別。如果無法實現,則會引發異常,例如 TypeError
或 ValueError
。
除非標記為 (D),否則以此方式定義的屬性不能使用例如 del
或 delattr()
刪除。
宏名稱 |
C 型別 |
Python 型別 |
---|---|---|
|
char |
|
|
short |
|
|
int |
|
|
long |
|
|
long long |
|
|
unsigned char |
|
|
unsigned int |
|
|
unsigned short |
|
|
unsigned long |
|
|
unsigned long long |
|
|
||
|
浮點數 |
|
|
double |
|
|
char (寫入為 0 或 1) |
|
|
const char* (*) |
|
|
const char[] (*) |
|
|
char (0-127) |
|
|
|
(*): 以零終止的 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¶
屬性名稱
-
const char *doc¶
可選文件字串
-
void *closure¶
可選的使用者資料指標,為 getter 和 setter 提供附加資料。
-
const char *name¶