1. Python3源碼—內建對象

1.1. Python內的對象

Python中的類和實例都是經過Python內的對象來實現的。Python中已經預先定義了一些類型對象。這些內建類型對象經過實例化,能夠建立內建類型對象的實例對象。app

在Python中,對象就是爲C中的結構體在堆上申請的一塊內存,通常來講,對象是不能被靜態初始化的,而且也不能在棧空間上生存。惟一的例外就是類型對象,Python中全部的內建的類型對象都是被靜態初始化的。函數

在Python中,一個對象一旦被建立,它在內存中的大小就是不變的了。這就意味着那些須要容納可變長度數據的對象只能在對象內維護一個指向一塊可變大小的內存區域的指針。ui

1.2. PyObject

PyObject是整個Python對象機制的核心,定義以下:指針

// object.h
typedef struct _object {
    _PyObject_HEAD_EXTRA
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;

其中_PyObject_HEAD_EXTRA定義以下:調試

// object.h
#ifdef Py_TRACE_REFS
/* Define pointers to support a doubly-linked list of all live heap objects. */
#define _PyObject_HEAD_EXTRA            \
    struct _object *_ob_next;           \
    struct _object *_ob_prev;

#define _PyObject_EXTRA_INIT 0, 0,

#else
#define _PyObject_HEAD_EXTRA
#define _PyObject_EXTRA_INIT
#endif

能夠看到release編譯時不會定義Py_TRACE_REFS。code

PyObject類中ob_refcnt與內存引用計數相關,ob_type用來指定一個對象類型的類型對象。在Python中,對象機制的核心一個是引用計數,一個就是類型信息。對象

每個Python對象除了必須有這個PyObject內容外,還應該佔有一些額外的內存,放置些其餘的東西。好比float對象除了PyObject,還有一個額外的double變量,以下定義:內存

// object.h
/* PyObject_HEAD defines the initial segment of every PyObject. */
#define PyObject_HEAD PyObject ob_base;

1.3. PyVarObject

把浮點對象這樣不包含可變長度數據的對象稱爲「定長對象」,而字符串對象這樣包含可變長度數據的對象稱爲「變長對象」,它們的區別在於定長對象的不一樣對象佔用的內存大小是同樣的,而變長對象的不一樣對象佔用的內存多是不同的。字符串

表示變長對象的結構體PyVarObject定義以下:get

// object.h
typedef struct {
    PyObject ob_base;
    Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;

每個可變Python對象除了有PyVarObject內容外,還佔有一些額外的內存,放置些其餘的東西。好比list對象爲變長對象,它的結構體以下:

// listobject.h
typedef struct {
    PyObject_VAR_HEAD
    PyObject **ob_item;
    Py_ssize_t allocated;
} PyListObject;

其中PyObject_VAR_HEAD定義了PyVarObject類型對象,以下:

// object.h
/* PyObject_VAR_HEAD defines the initial segment of all variable-size container objects. */
#define PyObject_VAR_HEAD     PyVarObject ob_base;

1.4. PyTypeObject

對象對應的類型對象定義以下:

// object.h
typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; 

    Py_ssize_t tp_basicsize, tp_itemsize;

    /* Methods to implement standard operations */
    destructor tp_dealloc;
    printfunc tp_print;
    
       // ...
} PyTypeObject;

定義中包含了許多信息,主要分爲4類:

  • 類型名,tp_name,主要是Python內部以及調試的時候使用;
  • 建立該類型對象時分配內存空間大小的信息,即tp_basicsize和tp_itemsize;
  • 與該類型對象相關聯的操做信息,諸如tp_print這樣的函數;
  • 類型的類型信息;

在PyTypeObject中定義了大量的函數指針,這些函數指針最終都會指向某個函數,或者指向NULL,能夠視爲類型對象中所定義的操做。在這些操做信息中,有三組很是重要的操做族:tp_as_number,tp_as_sequence和tp_as_mapping,分別指向PyNumberMethods,PySequenceMethods和PyMappingMethods函數族。PyNumberMethods、PySequenceMethods、PyMappingMethods分別定義了做爲一個數值對象、序列對象和關聯對象應該支持的操做。

類型對象的類型是PyType_Type:

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_reserved */
    (reprfunc)type_repr,               /* tp_repr */
    0,                                 /* tp_as_number */
    0,                                 /* tp_as_sequence */
    0,                                 /* tp_as_mapping */
    0,                                 /* 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 */
    0,                                 /* 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 */
};

1.5. Python對外提供的C API

Python的C API分爲兩類,一類稱爲範性的API(AOL,Abstract Object Layer),這類API都具備諸如PyObject_*的形式,能夠應用在任何Python對象上;另外一類是與類型相關的API(COL,Concrete Object Layer),這類API一般只能做用在某一種類型的對象上,對於每一種內建對象,Python都提供了這樣的一組API。

1.6 參考

  • Python源碼剖析

本文做者:whj0709
閱讀原文本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索