常用物件結構¶
Python 中定義物件型別時會用到大量的結構體。本節將描述這些結構體以及它們是如何使用的。
基本物件型別和宏¶
所有 Python 物件最終在記憶體中的物件表示的開頭共享少量欄位。這些欄位由 PyObject
和 PyVarObject
型別表示,這些型別又由一些宏的擴充套件定義,這些宏直接或間接地用於定義所有其他 Python 物件。其他宏可以在 引用計數 下找到。
-
type PyObject¶
- 屬於 有限 API 的一部分。(只有部分成員是穩定的 ABI 的一部分。)
所有物件型別都是此型別的擴充套件。這是一種包含 Python 將物件指標視為物件所需資訊的型別。在正常的 “release” 版本中,它僅包含物件的引用計數和指向相應型別物件的指標。實際上沒有宣告為
PyObject
,但每個指向 Python 物件的指標都可以轉換為 PyObject*。對成員的訪問必須使用宏Py_REFCNT
和Py_TYPE
完成。
-
type PyVarObject¶
- 屬於 有限 API 的一部分。(只有部分成員是穩定的 ABI 的一部分。)
這是
PyObject
的擴充套件,添加了ob_size
欄位。這僅用於具有某種長度概念的物件。此型別在 Python/C API 中不常出現。對成員的訪問必須使用宏Py_REFCNT
、Py_TYPE
和Py_SIZE
完成。
-
PyObject_VAR_HEAD¶
這是一個在宣告表示長度因例項而異的物件的的新型別時使用的宏。PyObject_VAR_HEAD 宏展開為
PyVarObject ob_base;
參見上面
PyVarObject
的文件。
-
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)¶
- 返回值:借用引用。
獲取 Python 物件 o 的型別。
返回一個 借用引用。
使用
Py_SET_TYPE()
函式設定物件型別。
-
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。
3.9 版本中新增。
-
Py_ssize_t Py_SIZE(PyVarObject *o)¶
獲取 Python 物件 o 的大小。
使用
Py_SET_SIZE()
函式設定物件大小。在 3.11 版本中變更:
Py_SIZE()
已更改為內聯靜態函式。引數型別不再是 const PyVarObject*。
-
void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size)¶
將物件 o 的大小設定為 size。
3.9 版本中新增。
-
PyVarObject_HEAD_INIT(type, size)¶
這是一個宏,它展開為新的
PyVarObject
型別的初始化值,包括ob_size
欄位。此宏展開為_PyObject_EXTRA_INIT 1, type, size,
實現函式和方法¶
-
type PyCFunction¶
- 屬於 穩定 ABI 的一部分。
用於在 C 中實現大多數 Python 可呼叫物件的函式的型別。此型別的函式接受兩個 PyObject* 引數並返回一個這樣的值。如果返回值為
NULL
,則應已設定異常。如果不是NULL
,則返回值被解釋為 Python 中公開的函式的返回值。該函式必須返回一個新的引用。函式簽名是
PyObject *PyCFunction(PyObject *self, PyObject *args);
-
type PyCFunctionWithKeywords¶
- 屬於 穩定 ABI 的一部分。
用於在 C 中實現具有簽名 METH_VARARGS | METH_KEYWORDS 的 Python 可呼叫物件的函式的型別。函式簽名是
PyObject *PyCFunctionWithKeywords(PyObject *self, PyObject *args, PyObject *kwargs);
-
type PyCFunctionFast¶
- 自 3.13 版本以來,屬於 穩定 ABI 的一部分。
用於在 C 中實現具有簽名
METH_FASTCALL
的 Python 可呼叫物件的函式的型別。函式簽名是PyObject *PyCFunctionFast(PyObject *self, PyObject *const *args, Py_ssize_t nargs);
-
type PyCFunctionFastWithKeywords¶
- 自 3.13 版本以來,屬於 穩定 ABI 的一部分。
用於在 C 中實現具有簽名 METH_FASTCALL | METH_KEYWORDS 的 Python 可呼叫物件的函式的型別。函式簽名是
PyObject *PyCFunctionFastWithKeywords(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames);
-
type 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 版本中新增。
-
type 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,第二個引數是一個 C 的 PyObject* 值陣列,表示引數,第三個引數是引數的數量(陣列的長度)。在 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
相同,但 在self
之後添加了defining_class
引數。3.9 版本中新增。
-
METH_NOARGS¶
如果使用
METH_NOARGS
標誌列出,則無引數的方法不需要檢查是否提供了引數。它們需要是PyCFunction
型別。第一個引數通常命名為 self,並將儲存對模組或物件例項的引用。在所有情況下,第二個引數將為NULL
。該函式必須有 2 個引數。由於第二個引數未使用,可以使用
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)
。
訪問擴充套件型別的屬性¶
-
type 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
定義,例如static PyMemberDef spam_type_members[] = { {"__vectorcalloffset__", Py_T_PYSSIZET, offsetof(Spam_object, vectorcall), Py_READONLY}, {NULL} /* Sentinel */ };
(你可能需要
#include <stddef.h>
來使用offsetof()
。)可以使用
"__dictoffset__"
和"__weaklistoffset__"
成員類似地定義舊式的偏移量tp_dictoffset
和tp_weaklistoffset
,但強烈建議擴充套件使用Py_TPFLAGS_MANAGED_DICT
和Py_TPFLAGS_MANAGED_WEAKREF
。在 3.12 版本中更改:
PyMemberDef
總是可用。之前,它需要包含"structmember.h"
。 -
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
開始的偏移量。當使用負的
basicsize
建立類時,只能作為Py_tp_members
slot
的一部分使用。在這種情況下,它是強制性的。此標誌僅在
PyType_Slot
中使用。在類建立期間設定tp_members
時,Python 會清除它並將PyMemberDef.offset
設定為從PyObject
結構開始的偏移量。
在 3.10 版本中更改: #include "structmember.h"
可用的 RESTRICTED
、READ_RESTRICTED
和 WRITE_RESTRICTED
宏已被棄用。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 |
|
|
||
|
float |
|
|
double |
|
|
char (表示為 0 或 1) |
|
|
const char* (*) |
|
|
const char[] (*) |
|
|
char (0-127) |
|
|
|
(*): 以空字元結尾、UTF8 編碼的 C 字串。對於
Py_T_STRING
,C 表示形式是指標;對於Py_T_STRING_INPLACE
,字串直接儲存在結構中。(**): 長度為 1 的字串。僅接受 ASCII 字元。
(只讀): 意味著
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
一起使用。
定義 Getters 和 Setters¶
-
type PyGetSetDef¶
- 屬於 穩定 ABI 的一部分(包括所有成員)。
用於為型別定義類似屬性的訪問的結構。另請參閱
PyTypeObject.tp_getset
插槽的描述。-
const char *name¶
屬性名稱
-
const char *doc¶
可選的文件字串
-
void *closure¶
可選的使用者資料指標,為 getter 和 setter 提供額外資料。
-
const char *name¶