前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python源码阅读笔记之对象体系(一)

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

作者头像
哒呵呵
发布2018-08-06 15:35:55
4630
发布2018-08-06 15:35:55
举报
文章被收录于专栏:鸿的学习笔记
代码语言:javascript
复制
二、对象体系
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的基础类型确实只有这么少。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-07-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档