阅读878 返回首页    go 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

  上一篇:go 国庆去哪里人最多?用 Python 抓取的热力图告诉你!
  下一篇:go Python老司机收藏夹的17个国外免费学习网站