python object
核心理念”Everything is an object“(虽然我暂时没有找到这句话的出处)
Basic
- identity: 内存中的唯一地址,获取函数
id() - type: 类型,获取函数
type() - value: 实际数据
Core
PyObject
CPython实现中的基础结构体,相当于所有Python类的基类
1 | // Include/pytypedefs.h |
PyVarObject
可变长度对象的基类
1 | // Include/object.h |
Type
PyTypeObject
类型对象本身也是一种对象
1 | // Include/pytypedefs.h |
对象协议&特殊方法
tp_name&name,module
通用格式: “[
- not be NULL
- name==
- 动态分配对象(例如用
type()而非class语句创建的类)的 tp_name 只有
- 动态分配对象(例如用
- module==[
.[ .]] - default=‘main’
1 | cls=type('mycls',(object,),{'__module__':'test_module','x':100}) |
tp_basicsize&basicsize, tp_itemsize&itemsize
- basicsize: 初始内存(结构体大小), 以字节为单位
- itemsize: 单个元素内存占用大小, 以字节为单位
变长对象(!=python可变对象)的这两个属性不可为空, 其实例大小=tp_basicsize+tp_itemsize*N(=ob_size)
注意: PyLongObject 的 N=abs(ob_size), 即其 ob_size 同时还存储了符号位
tp_repr&repr
dafault=“<%type_name object at %memory_address>”
1 | // Include/cpython/object.h |
tp_hash&hash
返回值 -1 代表发生 error 以及抛出 exception
tp_hash=PyObject_HashNotImplemented() 等效于 __hash_=None
1 | // Include/object.h |
tp_call&call
=NULL(当对象不可调用时)
tp_str&str
调用 str 类型的构造函数
被 print() 函数所使用, 兜底方案是 tp_repr
tp_getattro&getattr,getattribute
通常是 PyObject_GenericGetAttr()
1 | // Include/object.h |
tp_setattro&setattr,delattr
必须支持把 value 设置为 NULL 来删除对应属性
通常是 PyObject_GenericSetAttr()
1 | // Include/object.h |
tp_flags&flags
bit mask, default=Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
- Py_TPFLAGS_HEAPTYPE: 堆分配的对象
- Py_TPFLAGS_BASETYPE: type 能否被 subtyped(当此位被清除时, 类似 final class in Java)
- Py_TPFLAGS_READY: 对象完成 PyType_Ready() 初始化
- Py_TPFLAGS_READYING: 对象正在通过 PyType_Ready() 进行初始化
- Py_TPFLAGS_HAVE_GC: 对象支持垃圾回收, 需要与 tp_traverse 和 tp_clear 一起继承
- Py_TPFLAGS_DEFAULT: 包含 Py_TPFLAGS_HAVE_STACKLESS_EXTENSION
- Py_TPFLAGS_METHOD_DESCRIPTOR: 对象的行为类似于 unbound method
1 | # 内置函数 (设置了 Py_TPFLAGS_METHOD_DESCRIPTOR) |
- Py_TPFLAGS_LONG_SUBCLASS, Py_TPFLAGS_LIST_SUBCLASS, Py_TPFLAGS_TUPLE_SUBCLASS, Py_TPFLAGS_BYTES_SUBCLASS, Py_TPFLAGS_UNICODE_SUBCLASS, Py_TPFLAGS_DICT_SUBCLASS, Py_TPFLAGS_BASE_EXC_SUBCLASS, Py_TPFLAGS_TYPE_SUBCLASS: 被
PyLong_Check()等函数用于判断是否是内置类型的子类 - Py_TPFLAGS_HAVE_FINALIZE: tp_finalize 属性存在, python3.8后解释器假定 tp_finalize 始终存在, 即此标志位被移除
- Py_TPFLAGS_HAVE_VECTORCALL: 对象实现了 vectorcall 协议
- Py_TPFLAGS_IMMUTABLETYPE: 对象是不可变的, 即其属性不能被修改和删除
- Py_TPFLAGS_DISALLOW_INSTANTIATION: 对象不能被实例化, 即
tp_new=NULL; 只能在创建类型之前设置此标志位 - Py_TPFLAGS_MAPPING: 对象的实例在作为 match 语句的匹配目标时, 可以被视为 Mapping 进行模式匹配; 与 Py_TPFLAGS_SEQUENCE 互斥
- Py_TPFLAGS_SEQUENCE: 对象的实例在作为 match 语句的匹配目标时, 可以被视为 Sequence 进行模式匹配; 与 Py_TPFLAGS_MAPPING 互斥
tp_doc&doc
以 NULL 结尾的字符串, 代表此对象的 docstring
tp_iter&iter
返回对象的迭代器; 存在与否通常对应着对象实例是否可迭代(sequence 除外)
1 | // Include/object.h |
tp_iternext&next
必须返回NULL(当迭代器耗尽时/当发生错误时); 不一定设置 StopInteration 异常
1 | // Include/object.h |
tp_base&base
指向父类(单继承)
default=&PyBaseObject_Type
tp_dict&dict
类型本身的属性字典
在 PyType_Ready() 时被完善
default=NULL, 则PyType_Ready() 会直接赋值
tp_descr_get&get
1 | // Include/object.h |
tp_descr_set&set,delete
1 | // Include/object.h |
tp_init&init
在 tp_new 后被调用; 调用的是 tp_new 返回值的 tp_init; tp_int 不生效(当 tp_new 返回值不是预期 type 本身或其子类的实例时)
1 | // Include/object.h |
tp_new&new
调用 subtype->tp_alloc 来为对象分配空间, 然后只执行绝对必要的初始化操作(其他可以忽略或重复的初始化操作应该被放到 tp_init)
经验: 所有初始化都在 tp_new(不可变类型)/tp_init(可变类型) 中进行
1 | // Include/object.h |
tp_bases&bases
default=NULL(READONLY)
在 type 初始化时填充此属性
多重继承不适用于静态定义的类型, 将会只使用 bases 中的第一个
tp_mro&mro
default=NULL(READONLY)
在 type 初始化时填充此属性
方法解析顺序: type -> … -> object
tp_finalize&del
在实例的最终化时被调用(在对象被 tp_dealloc 释放之前), 也可能被 GC 调用(当实例处于 isolated reference cycles 时)
不会修改异常状态
协议集合
PyAsyncMethods *tp_as_async
1 | // Include/cpython/object.h |
PyNumberMethods *tp_as_number
1 | // Include/cpython/object.h |
PySequenceMethods *tp_as_sequence
1 | // Include/cpython/object.h |
PyMappingMethods *tp_as_mapping
1 | // Include/cpython/object.h |
PyBufferProcs *tp_as_buffer
常见场景: producer 和 consumer 通过共享内存来传递信息
1 | // Include/cpython/object.h |
richcmpfunc tp_richcompare
支持的比较: Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE
返回结果: Py_True, Py_False, Py_NotImplemented(比较未定义), NULL(发生错误)
1 | // Include/object.h |
PyMethodDef *tp_methods
1 | // Include/methodobject.h |
PyMemberDef *tp_members
1 | // Include/structmember.h |
PyGetSetDef *tp_getset
1 | // Include/descrobject.h |
Common Types
PyLongObject
所有整数都借助任意长度的 PyLongObject 对象实现(采用PyVarObject头)
1 | // Include/cpython/longintrepr.h |
PyFloatObject
1 | // Include/cpython/floatobject.h |
PyUnicodeObject
1 | // Include/cpython/unicodeobject.h |
PyListObject
1 | // Include/cpython/listobject.h |
PyDictObject
1 | // Include/cpython/dictobject.h |
PySliceObject
1 | // Include/sliceobject.h |