社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python 源码阅读:类型

Python开发者 • 8 年前 • 850 次点击  

(点击上方蓝字,快速关注我们)


来源: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


即: 大量函数指针决定了该类型的具体行为


看完本文有收获?请转发分享给更多人

关注「Python开发者」,提升Python技能


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/U01mP2HxDa
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/3570