Python源码阅读:type

首先看一个例子:

 1 >>> a = 1
 2 >>> a
 3 1
 4 >>> type(a)
 5 <type 'int'>
 6 >>> type(type(a))
 7 <type 'type'>
 8 >>> type(int)
 9 <type 'type'>
10 >>> type(type(type(a)))
11 <type 'type'>
12 >>> type(type(int))
13 <type 'type'>

我们反向推导一个int对象是怎么生成的。

1. 定义一种类型叫PyTypeObject

代码位置 Include/object.h

 1 typedef struct _typeobject {
 2 
 3   /* MARK: base, 注意, 是个变长对象*/
 4   PyObject_VAR_HEAD
 5   const char *tp_name; /* For printing, in format "." */ //类型名
 6   Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ // 创建该类型对象时分配的内存空间大小
 7 
 8   // 一堆方法定义, 函数和指针
 9   /* Methods to implement standard operations */
10   printfunc tp_print;
11   hashfunc tp_hash;
12 
13   /* Method suites for standard classes */
14   PyNumberMethods *tp_as_number;   // 数值对象操作
15   PySequenceMethods *tp_as_sequence; // 序列对象操作
16   PyMappingMethods *tp_as_mapping; // 字典对象操作
17 
18   // 一堆属性定义
19   ....
20 
21 } PyTypeObject;

说明:

 1 1. tp_name
 2 类型名, 这里是"type"
 3 
 4 2. PyVarObject_HEAD_INIT(&PyType_Type, 0)
 5 PyVarObject_HEAD_INIT, 这个方法在 Include/object.h中,
 6 等价于
 7         ob_refcnt = 1
 8         *ob_type = &PyType_Type
 9         ob_size = 0
10 
11 即, PyType_Type的类型是其本身!1. tp_name
12 类型名, 这里是"type"
13 
14 2. PyVarObject_HEAD_INIT(&PyType_Type, 0)
15 PyVarObject_HEAD_INIT, 这个方法在 Include/object.h中,
16 等价于
17         ob_refcnt = 1
18         *ob_type = &PyType_Type
19         ob_size = 0
20 
21 即, PyType_Type的类型是其本身!

所有Type都是PyTypeObject的”实例”: PyType_Type/PyInt_Type。

2. 然后, 用PyTypeObject初始化得到一个对象PyType_Type

代码位置 Objects/typeobject.c

 1 PyTypeObject PyType_Type = {
 2   PyVarObject_HEAD_INIT(&PyType_Type, 0)
 3   "type",                                     /* tp_name */
 4   sizeof(PyHeapTypeObject),                   /* tp_basicsize */
 5   sizeof(PyMemberDef),                        /* tp_itemsize */
 6   (destructor)type_dealloc,                   /* tp_dealloc */
 7  
 8   // type对象的方法和属性初始化值
 9   .....
10  
11 };

说明:

 1 1. tp_name
 2 类型名, 这里是"type"
 3  
 4 2. PyVarObject_HEAD_INIT(&PyType_Type, 0)
 5 PyVarObject_HEAD_INIT, 这个方法在 Include/object.h中,
 6 等价于
 7         ob_refcnt = 1
 8         *ob_type = &PyType_Type
 9         ob_size = 0
10  
11 即, PyType_Type的类型是其本身!1. tp_name
12 类型名, 这里是"type"
13  
14 2. PyVarObject_HEAD_INIT(&PyType_Type, 0)
15 PyVarObject_HEAD_INIT, 这个方法在 Include/object.h中,
16 等价于
17         ob_refcnt = 1
18         *ob_type = &PyType_Type
19         ob_size = 0
20  
21 即, PyType_Type的类型是其本身!1. tp_name
22 类型名, 这里是"type"
23  
24 2. PyVarObject_HEAD_INIT(&PyType_Type, 0)
25 PyVarObject_HEAD_INIT, 这个方法在 Include/object.h中,
26 等价于
27         ob_refcnt = 1
28         *ob_type = &PyType_Type
29         ob_size = 0
30  
31 即, PyType_Type的类型是其本身!

结构

第一张图, 箭头表示实例化(google doc用不是很熟找不到对应类型的箭头)

第二张图, 箭表示指向

1 # 1. int 的 类型 是`type`
2 >>> type(int)
3  
4 # 2. type 的类型 还是`type`, 对应上面说明第二点
5 >>> 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

其结构图为:

即就是python的如下代码:

1 >>> type(1)
2 <type 'int'>
3  
4 >>> type(type(1))
5 <type 'type'>

4. 最后, 生成一个整数对象int

代码位置 Include/intobject.h

1 typedef struct {
2     PyObject_HEAD
3     long ob_ival;
4 } PyIntObject;
5 说明:
6 1. PyIntObject为整数类型,声明一个整数后得到整数对象, 对象ob_type指向PyInt_type对象

 

5.到这里, 总结下

1. 一切都是对象
 
2. PyType_Type / PyInt_Type / PyString_Type ....等,这些是`类型对象`, 可以认为是同级, 都是PyTypeObject这种`类型`的实例!
 
3. 虽然是同级,但是其他PyXXX_Type, 其类型指向 PyType_Type, PyType_Type 的类型指向自己, 它是所有类型的`类型`
 
4. PyTypeObject 是一个变长对象
 
5. 每个object, 例如PyIntObject都属于一种`类型`,object初始化时进行关联。

6. 多态是如何实现的?

 对象的多态, 例如hash:

1 >>> hash(1)
2 1
3 >>> hash("abc")
4 1453079729188098211

  从上面数据结构可以看到, 方法及属性, 在不同Type实例化时就确定了:

 1 PyTypeObject PyInt_Type = {
 2     ...
 3     (hashfunc)int_hash,                         /* tp_hash */
 4     ...
 5 }
 6  
 7 PyTypeObject PyString_Type = {
 8     ...
 9     (hashfunc)string_hash,                      /* tp_hash */
10     ...
11 }

Python内部传递的是泛型指针PyObject *, 函数调用时, 找到其类型* ob_type, 然后调用,即:

object -> ob_type -> tp_hash

猜你喜欢

转载自www.cnblogs.com/qianyeliange/p/9430049.html