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)

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

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏何俊林

从面试题中看Java的Reference(引用)

前言:四大引用,是一个古老的知识,今天看下 Harlber 授权公众号独家推送的文章, Harlber 的简书地址 :http://www.jianshu.co...

37610
来自专栏互联网大杂烩

腾讯面试

时间:2017年3月5号 这次面试和之前的面试差不多,一开始聊项目。聊了项目之后就问基础了,项目的话就不说了。

712
来自专栏空帆船w

Java的强引用,软引用,弱引用,虚引用及其使用场景

从 JDK1.2 版本开始,Java 把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引...

2632
来自专栏cmazxiaoma的架构师之路

关于牛客网的JAVA面试题错题总结以及归纳(1)

1373
来自专栏java初学

java — 垃圾回收

39410
来自专栏向治洪

java的四种引用类型

java的引用分为四个等级:4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。 ⑴强引用(StrongReference) 强引用是使用最普遍的引用。...

1915
来自专栏Hongten

python开发_function annotations

在看python的API的时候,发现了一个有趣的东东,即:python的方法(函数)注解(Function Annotation)

1212
来自专栏JavaEdge

垃圾收集策略静态内存分配和回收动态内存分配和回收1 Java堆内存的回收2 回收无效对象的过程3 方法区的内存回收4 垃圾收集算法5 Java中引用的种类

3459
来自专栏刘望舒

Java虚拟机(三)垃圾标记算法与Java对象的生命周期

前言 这一节我们来简单的介绍垃圾收集器,并学习垃圾标记的算法:引用计数算法和根搜索算法,为了更好的理解根搜索算法,会在文章的最后介绍Java对象在虚拟机中的...

1926
来自专栏个人分享

JAVA 几种引用类型学习

1、对象的强、软、弱和虚引用     在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及(re...

2962

扫码关注云+社区

领取腾讯云代金券