zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    通用接口测试用例设计(转载)
    Jenkin配置执行远程shell命令
    Jenkins创建Maven项目及SSH部署
    Jenkins插件安装和系统配置
    Jenkins+svn+ant+tomcat持续集成
    Jmeter之Bean shell使用(二)
    numba,让python速度提升百倍
    哪吒票房超复联4,100行python代码抓取豆瓣短评,看看网友怎么说
    小白如何入门 Python 爬虫?
    干货!小白入门Python数据科学全教程
  • 原文地址:https://www.cnblogs.com/qianyeliange/p/9430049.html
Copyright © 2011-2022 走看看