878
Python
Python 源码阅读:类型
这篇主要涉及Python对象的类型机制
有点绕, 一定要思维清晰的时候再看哦:)
一个例子
1
>>>type(a)
#等价的两个
>>>type(type(a))
>>>type(int)
#还是等价的两个
>>>type(type(type(a)))
>>>type(type(int))
我们反向推导一个int对象是怎么生成的.
1. 首先, 定义一种类型叫PyTypeObject
代码位置 Include/object.h
定义
typedefstruct_typeobject{
/* MARK: base, 注意, 是个变长对象*/
PyObject_VAR_HEAD
constchar*tp_name;/* For printing, in format "." *///类型名
Py_ssize_ttp_basicsize,tp_itemsize;/* For allocation */// 创建该类型对象时分配的内存空间大小
// 一堆方法定义, 函数和指针
/* Methods to implement standard operations */
printfunctp_print;
hashfunctp_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,)
PyVarObject_HEAD_INIT,这个方法在Include/object.h中,
等价于
ob_refcnt=1
*ob_type= &PyType_Type
ob_size=
即,PyType_Type的类型是其本身!1.tp_name
类型名,这里是"type"
2.PyVarObject_HEAD_INIT(&PyType_Type,)
PyVarObject_HEAD_INIT,这个方法在Include/object.h中,
等价于
ob_refcnt=1
*ob_type= &PyType_Type
ob_size=
即,PyType_Type的类型是其本身!
所有Type都是PyTypeObject的”实例”: PyType_Type/PyInt_Type
2. 然后, 用PyTypeObject初始化得到一个对象PyType_Type
代码位置 Objects/typeobject.c
定义
PyTypeObjectPyType_Type={
PyVarObject_HEAD_INIT(&PyType_Type,)
"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,)
PyVarObject_HEAD_INIT,这个方法在Include/object.h中,
等价于
ob_refcnt=1
*ob_type= &PyType_Type
ob_size=
即,PyType_Type的类型是其本身!1.tp_name
类型名,这里是"type"
2.PyVarObject_HEAD_INIT(&PyType_Type,)
PyVarObject_HEAD_INIT,这个方法在Include/object.h中,
等价于
ob_refcnt=1
*ob_type= &PyType_Type
ob_size=
即,PyType_Type的类型是其本身!1.tp_name
类型名,这里是"type"
2.PyVarObject_HEAD_INIT(&PyType_Type,)
PyVarObject_HEAD_INIT,这个方法在Include/object.h中,
等价于
ob_refcnt=1
*ob_type= &PyType_Type
ob_size=
即,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
定义
PyTypeObjectPyInt_Type={
PyVarObject_HEAD_INIT(&PyType_Type,)
"int",
sizeof(PyIntObject),
,
// int类型的相关方法和属性值
....
(hashfunc)int_hash,/* tp_hash */
};
说明
1."int"
PyInt_Type的类型名是int
2.PyVarObject_HEAD_INIT(&PyType_Type,)
PyInt_Type的
*ob_type= &PyType_Type
结构
使用
>>>type(1)
>>>type(type(1))
4. 最后, 生成一个整数对象int
代码位置 Include/intobject.h
定义
typedefstruct{
PyObject_HEAD
longob_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")
从上面数据结构可以看到, 方法及属性, 在不同Type实例化时就确定了
PyTypeObjectPyInt_Type={
...
(hashfunc)int_hash,/* tp_hash */
...
}
PyTypeObjectPyString_Type={
...
(hashfunc)string_hash,/* tp_hash */
...
}
Python内部传递的是泛型指针PyObject *, 函数调用时, 找到其类型* ob_type, 然后调用
object -> ob_type -> tp_hash
即: 大量函数指针决定了该类型的具体行为
来源:wklken
编辑 | 码哥
图片源于网络,版权归原作者所有
最后更新:2017-10-09 00:53:52