专栏首页鸿的学习笔记python源码阅读笔记之对象体系(一)

python源码阅读笔记之对象体系(一)

二、对象体系
pythoner有句话常说:“一切皆对象”,说是这么说,但是理解吗?
首先,我们来看看对象的定义:就是数据和基于这些数据的操作的集合。
python是用C编写,C里面可没有对象的概念,那这个究竟是什么呢?
在python中,对象实际是为C的结构体在堆上申请的一片内存。这里的堆是Heap的概念。

让我们还是从object.h这个头文件一窥究竟吧
在文件开头,有一长串注释,在里面有下面几个要点:
1.Objects are structures allocated on the heap.这就是上面所说的,对象实际是为C的结构体在堆上申请的一片内存。
2.内存管理的核心:An object has a 'reference count' that is increased or decreased when a
pointer to the object is copied or deleted; 这也是GIL锁的原因之一。
3.对象一旦分配,便不可更改。Objects do not float around in memory; once allocated an object keeps
the same size and address.这是为python的内存管理服务的。
4.所有对象都有一个核心东西PyObject。Objects are always accessed through pointers of the type 'PyObject *'.
5.A standard interface exists for objects that contain an array of items
whose size is determined when the object is allocated.

注释里提到了PyObject,那这是啥东西呢?
typedef struct _object {
    PyObject_HEAD
} PyObject;

#define PyObject_HEAD                   \
    _PyObject_HEAD_EXTRA                \
    Py_ssize_t ob_refcnt;               \
    struct _typeobject *ob_type;
/*垃圾回收里的标记清除会用到*/
#define _PyObject_HEAD_EXTRA            \
    struct _object *_ob_next;           \
    struct _object *_ob_prev;    
 
Py_ssize_t是python的一个有趣的类型,是为了解决CPU位数问题的一个整形
在pyport.h可以看见定义
typedef ssize_t         Py_ssize_t;

python里面还有一种定义,是包含着个数信息的那种对象:
typedef struct {
    PyObject_VAR_HEAD
} PyVarObject;

 */
#define PyObject_VAR_HEAD               \
    PyObject_HEAD                       \
    Py_ssize_t ob_size; /* Number of items in variable part */

如注释所述,还包含items的个数信息

占用内存空间的信息在哪呢?隐含在_typeobject这个里面
typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; /* For printing, in format "<module>.<name>" */
    Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

    /* Methods to implement standard operations */

    destructor tp_dealloc;
    printfunc tp_print;
    getattrfunc tp_getattr;
    setattrfunc tp_setattr;
    cmpfunc tp_compare;
    reprfunc tp_repr;

    /* Method suites for standard classes */

    PyNumberMethods *tp_as_number;
    PySequenceMethods *tp_as_sequence;
    PyMappingMethods *tp_as_mapping;

    /* More standard operations (here for binary compatibility) */

    hashfunc tp_hash;
    ternaryfunc tp_call;
    reprfunc tp_str;
    getattrofunc tp_getattro;
    setattrofunc tp_setattro;

    /* Functions to access object as input/output buffer */
    PyBufferProcs *tp_as_buffer;

    /* Flags to define presence of optional/expanded features */
    long tp_flags;

    const char *tp_doc; /* Documentation string */

    /* Assigned meaning in release 2.0 */
    /* call function for all accessible objects */
    traverseproc tp_traverse;

    /* delete references to contained objects */
    inquiry tp_clear;

    /* Assigned meaning in release 2.1 */
    /* rich comparisons */
    richcmpfunc tp_richcompare;

    /* weak reference enabler */
    Py_ssize_t tp_weaklistoffset;

    /* Added in release 2.2 */
    /* Iterators */
    getiterfunc tp_iter;
    iternextfunc tp_iternext;

    /* Attribute descriptor and subclassing stuff */
    struct PyMethodDef *tp_methods;
    struct PyMemberDef *tp_members;
    struct PyGetSetDef *tp_getset;
    struct _typeobject *tp_base;
    PyObject *tp_dict;
    descrgetfunc tp_descr_get;
    descrsetfunc tp_descr_set;
    Py_ssize_t tp_dictoffset;
    initproc tp_init;
    allocfunc tp_alloc;
    newfunc tp_new;
    freefunc tp_free; /* Low-level free-memory routine */
    inquiry tp_is_gc; /* For PyObject_IS_GC */
    PyObject *tp_bases;
    PyObject *tp_mro; /* method resolution order */
    PyObject *tp_cache;
    PyObject *tp_subclasses;
    PyObject *tp_weaklist;
    destructor tp_del;

    /* Type attribute cache version tag. Added in version 2.6 */
    unsigned int tp_version_tag;

#ifdef COUNT_ALLOCS
    /* these must be last and never explicitly initialized */
    Py_ssize_t tp_allocs;
    Py_ssize_t tp_frees;
    Py_ssize_t tp_maxalloc;
    struct _typeobject *tp_prev;
    struct _typeobject *tp_next;
#endif
} PyTypeObject;

从上面可以看出:
*tp_name 类型名
tp_basicsize, tp_itemsize内存分配的大小
一些标准操作,例如print
类型信息

那么对象是如何创建的呢?
1.C API,也就是python的C扩展包 2.内建对象的API

从上述的结构体当中,可以看到这么一段话:
/* Method suites for standard classes */

PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;

这实际上指的是每一种对象都有着三种操作,数值,序列,关联
这也是为啥一个字符串你可以进行如下操作:
a = '234'
for i in a:
    print(i)
 
2
3
4

python的类型也是一个对象,每一个对象都对应着一个类型,比如
a = 1
a对应着的是int类型
那类型的类型是啥呢?我们进入到typeobject.h中看看
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 */
    0,                                          /* tp_print */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    0,                                  /* tp_compare */
    (reprfunc)type_repr,                        /* tp_repr */
    0,                                          /* tp_as_number */
    0,                                          /* tp_as_sequence */
    0,                                          /* tp_as_mapping */
    (hashfunc)_Py_HashPointer,                  /* tp_hash */
    (ternaryfunc)type_call,                     /* tp_call */
    0,                                          /* tp_str */
    (getattrofunc)type_getattro,                /* tp_getattro */
    (setattrofunc)type_setattro,                /* tp_setattro */
    0,                                          /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
        Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS,         /* tp_flags */
    type_doc,                                   /* tp_doc */
    (traverseproc)type_traverse,                /* tp_traverse */
    (inquiry)type_clear,                        /* tp_clear */
    type_richcompare,                                           /* tp_richcompare */
    offsetof(PyTypeObject, tp_weaklist),        /* tp_weaklistoffset */
    0,                                          /* tp_iter */
    0,                                          /* tp_iternext */
    type_methods,                               /* tp_methods */
    type_members,                               /* tp_members */
    type_getsets,                               /* tp_getset */
    0,                                          /* tp_base */
    0,                                          /* tp_dict */
    0,                                          /* tp_descr_get */
    0,                                          /* tp_descr_set */
    offsetof(PyTypeObject, tp_dict),            /* tp_dictoffset */
    type_init,                                  /* tp_init */
    0,                                          /* tp_alloc */
    type_new,                                   /* tp_new */
    PyObject_GC_Del,                            /* tp_free */
    (inquiry)type_is_gc,                        /* tp_is_gc */
};

这就是传说中的metaclass,下述就可以看出了
    "type",                                     /* tp_name */
在python中输入如下:    
type(type)
Out[9]: type

好了现在我们可以梳理一下大致的python的对象类型:(采用的《python源码剖析》里的,我觉得这里的分类很好)
Fundamental对象:类型对象
Numeric对象:long, float, boolean
Sequence对象:list, tuple, string
Mapping对象:dict
Internal对象:虚拟机运行时对象function, code, frame, module, method

注:很可怜的,python的基础类型确实只有这么少。

本文分享自微信公众号 - 鸿的学习笔记(shujuxuexizhilu),作者:鸿

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-07-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python源码阅读笔记之字符串对象

    哒呵呵
  • Scala的函数

    前文已经提到Scala变量的用法,现在聊聊函数。在Scala里,函数的定义很简单。例如:

    哒呵呵
  • Python的实例属性和类属性

    类属性指的是定义在class内部的,而实例属性是则与某个特定的实例(对象)有关。定义过于抽象了,看看例子。

    哒呵呵
  • LeetCode 752. 打开转盘锁(图的BFS最短路径)

    你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。...

    Michael阿明
  • 2018年Java程序员最新BAT面试题

    美的让人心动
  • 谷歌传奇Jeff Dean给创业者的一小时AI讲座 | 86页PPT+视频

    李林 若朴 编译整理 量子位 出品 | 公众号 QbitAI ? 少年,你知道Jeff Dean么? 传奇一般的Jeff Dean现在领导着Google Bra...

    量子位
  • Vijos P1785 同学排序【模拟】

    同学排序 描述 现有m位同学,第1位同学为1号,第2位同学为2号,依次第m位同学为m号。要求双号的学生站出来,然后余下的重新组合,组合完后,再次让双号的学生站出...

    Angel_Kitty
  • 0基础学Python从哪入手?3个月快速学会Python的秘诀是什么?

    题主如果想要利用python爬取数据资料,本人目前也正在学习Python网络爬虫,我就从爬虫谈谈python的学习。

    python学习教程
  • [SEOer]为网站设置优秀的标题和描述

    例如: WordPress插件下载,WordPress主题,WordPress资源,钻芒博客-记录生活,学会感恩

    AlexTao
  • hashCode,MD5,SHA-1的区别和碰撞量级

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    逝兮诚

扫码关注云+社区

领取腾讯云代金券