PYTHON 源码阅读 - 类型,python源码,未经作者许可,禁止转载!
PYTHON 源码阅读 - 类型,python源码,未经作者许可,禁止转载!
本文作者: 编橙之家 - wklken 。未经作者许可,禁止转载!欢迎加入编橙之家 专栏作者。
这篇主要涉及Python对象的类型机制
有点绕, 一定要思维清晰的时候再看哦:)
一个例子
>>> a = 1 >>> a 1 >>> type(a) #等价的两个 >>> type(type(a)) >>> type(int) #还是等价的两个 >>> type(type(type(a))) >>> type(type(int))
我们反向推导一个int
对象是怎么生成的.
1. 首先, 定义一种类型叫PyTypeObject
代码位置 Include/object.h
定义
typedef struct _typeobject { /* MARK: base, 注意, 是个变长对象*/ PyObject_VAR_HEAD const char *tp_name; /* For printing, in format "." */ //类型名 Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ // 创建该类型对象时分配的内存空间大小 // 一堆方法定义, 函数和指针 /* Methods to implement standard operations */ printfunc tp_print; hashfunc tp_hash; /* Method suites for standard classes */ PyNumberMethods *tp_as_number; // 数值对象操作 PySequenceMethods *tp_as_sequence; // 序列对象操作 PyMappingMethods *tp_as_mapping; // 字典对象操作 // 一堆属性定义 .... } PyTypeObject;
说明
1. tp_name 类型名, 这里是"type" 2. PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT, 这个方法在 Include/object.h中, 等价于 ob_refcnt = 1 *ob_type = &PyType_Type ob_size = 0 即, PyType_Type的类型是其本身!1. tp_name 类型名, 这里是"type" 2. PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT, 这个方法在 Include/object.h中, 等价于 ob_refcnt = 1 *ob_type = &PyType_Type ob_size = 0 即, PyType_Type的类型是其本身!
所有Type都是PyTypeObject的”实例”: PyType_Type/PyInt_Type
2. 然后, 用PyTypeObject初始化得到一个对象PyType_Type
代码位置 Objects/typeobject.c
定义
PyTypeObject PyType_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "type", /* tp_name */ sizeof(PyHeapTypeObject), /* tp_basicsize */ sizeof(PyMemberDef), /* tp_itemsize */ (destructor)type_dealloc, /* tp_dealloc */ // type对象的方法和属性初始化值 ..... };
说明
1. tp_name 类型名, 这里是"type" 2. PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT, 这个方法在 Include/object.h中, 等价于 ob_refcnt = 1 *ob_type = &PyType_Type ob_size = 0 即, PyType_Type的类型是其本身!1. tp_name 类型名, 这里是"type" 2. PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT, 这个方法在 Include/object.h中, 等价于 ob_refcnt = 1 *ob_type = &PyType_Type ob_size = 0 即, PyType_Type的类型是其本身!1. tp_name 类型名, 这里是"type" 2. PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT, 这个方法在 Include/object.h中, 等价于 ob_refcnt = 1 *ob_type = &PyType_Type ob_size = 0 即, PyType_Type的类型是其本身!
结构
第一张图, 箭头表示实例化
(google doc用不是很熟找不到对应类型的箭头)
第二张图, 箭头表示指向
使用
# 1. int 的 类型 是`type` >>> type(int) # 2. type 的类型 还是`type`, 对应上面说明第二点 >>> type(type(int))
注意: 无论任何时候, ob_type指向的是 PyTypeObject的实例: PyType_Type/PyInt_Type…
3. 再然后, 定义具体的类型, 这里以PyInt_Type为例子
代码位置 Objects/intobject.c
定义
PyTypeObject PyInt_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "int", sizeof(PyIntObject), 0, // int类型的相关方法和属性值 .... (hashfunc)int_hash, /* tp_hash */ };
说明
1. "int" PyInt_Type的类型名是int 2.PyVarObject_HEAD_INIT(&PyType_Type, 0) PyInt_Type的 *ob_type = &PyType_Type
结构
使用
>>> type(1) <type 'int'> >>> type(type(1)) <type 'type'>
4. 最后, 生成一个整数对象int
代码位置 Include/intobject.h
定义
typedef struct { PyObject_HEAD long ob_ival; } PyIntObject;
结构
1. PyIntObject为整数类型 2. 声明一个整数后得到整数对象 3. 对象ob_type指向PyInt_type对象
到这里, 总结下
1. 一切都是对象 2. PyType_Type / PyInt_Type / PyString_Type ....等 这些是`类型对象`, 可以认为是同级, 都是PyTypeObject这种`类型`的实例! 3. 虽然是同级, 但是其他PyXXX_Type, 其类型指向 PyType_Type PyType_Type 的类型指向自己, 它是所有类型的`类型` 4. PyTypeObject 是一个变长对象 5. 每个object, 例如PyIntObject都属于一种`类型` object初始化时进行关联
多态是如何实现的?
对象的多态, 例如hash
>>> hash(1) 1 >>> hash("abc") 1453079729188098211
从上面数据结构可以看到, 方法及属性, 在不同Type实例化时就确定了
PyTypeObject PyInt_Type = { ... (hashfunc)int_hash, /* tp_hash */ ... } PyTypeObject PyString_Type = { ... (hashfunc)string_hash, /* tp_hash */ ... }
Python内部传递的是泛型指针PyObject *
, 函数调用时, 找到其类型* ob_type
, 然后调用
object -> ob_type -> tp_hash
即: 大量函数指针决定了该类型的具体行为
changelog
2014-08-05 first version
打赏支持我写出更多好文章,谢谢!
打赏作者
打赏支持我写出更多好文章,谢谢!
任选一种支付方式
评论关闭