概要
Pythonの構造を理解する助けとして、C APIのドキュメントを読み砕いていく。
内容
環境
Python 3.7 (CPython)に話を固定したいが、必ずしもそうはならない。
tree (コミット; ブランチ)
(↑ githubのリンク)
前置き
Noneに対するPyTypeObjectは、Python/C APIでは直接公開されていないので注意。
Noneは単量子 (singleton) なので、オブジェクトの同一性テスト (C では==) を使うだけで十分であり、 PyNone_Check()関数はない。
PyObject* Py_None
<概説>
PythonにおけるNoneオブジェクトで、値がないことを表す。
参照カウントは他のオブジェクトと同様に扱う。メソッドはない。
<定義>
定義 (cpython/Include/object.h)
PyAPI_DATA(PyObject) _Py_NoneStruct; /* Don't use this directly */
# define Py_None (&_Py_NoneStruct)
(定義出典)
<定義補足>
定義 (cpython/Include/object.h)
PyTypeObject _PyNone_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"NoneType",
0,
0,
none_dealloc, /*tp_dealloc*/ /*never called*/
0, /*tp_vectorcall_offset*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_as_async*/
none_repr, /*tp_repr*/
&none_as_number, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call */
0, /*tp_str */
0, /*tp_getattro */
0, /*tp_setattro */
0, /*tp_as_buffer */
Py_TPFLAGS_DEFAULT, /*tp_flags */
0, /*tp_doc */
0, /*tp_traverse */
0, /*tp_clear */
0, /*tp_richcompare */
0, /*tp_weaklistoffset */
0, /*tp_iter */
0, /*tp_iternext */
0, /*tp_methods */
0, /*tp_members */
0, /*tp_getset */
0, /*tp_base */
0, /*tp_dict */
0, /*tp_descr_get */
0, /*tp_descr_set */
0, /*tp_dictoffset */
0, /*tp_init */
0, /*tp_alloc */
none_new, /*tp_new */
};
PyObject _Py_NoneStruct = {
_PyObject_EXTRA_INIT
1, &_PyNone_Type
};
(定義出典)
<使用例>
使用例 (cpython/Objects/stringlib/unicode_format.h)
if (conversion == '\0') {
conversion_str = Py_None;
(使用例出典)
Py_RETURN_NONE
<概説>
C関数からのPy_Noneの返却を適切に扱う。
(Noneの参照カウントをインクリメントして返す。)
<定義>
定義 (cpython/Include/object.h)
# define Py_RETURN_NONE return Py_NewRef(Py_None)
(定義出典)
<使用例>
使用例 (cpython/Modules/readline.c)
Py_RETURN_NONE;
}
(使用例出典)
参考にさせていただいた本・ページ
感想
バージョンが混ざってしまっているかもしれないが、雰囲気を掴むことが目的なので、今のところそこを修正する予定はない。