PyHeapTypeObject http://blog.sina.com.cn/s/blog_72d1932a0101gcg3.html

来源:互联网 发布:淘宝改价新规则 编辑:程序博客网 时间:2024/04/30 22:24
  这几天在看《Python源码剖析》一书,一路看来总感觉讲得挺清楚的,绝对是一本好书。可是看到第十二章的“从type对象到class对象”时就感觉一直看不懂。遂google之,未果。于是自己看源码。
        感觉在看关于slot的时候迷迷糊糊的,又突然冒出个PyHeapTypeObject,这有什么用?
        首先,从typeobject.c的PyType_Ready函数看起,进入add_operators(type)函数。里面主要调用了init_slotdefs(),在init_slotdefs()中,它对static slotdefs数组进行排序,里面主要调用了C库函数qsort (void qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) );),该函数的排序利用了slotdef的offset项。
        之后利用各slotdef项的offset定位PyHeapTypeObject中的相对应的操作,赋给ptr,之后跳过一系列错误处理,就到了PyDescr_NewWrapper(),在该函数中新建了一个PyWrapperDescr_Type对象,并将它的d_base指向了刚才获取的ptr(PyHeapTypeObject中相对应的处理函数),以及将d_base指向了slotdef
        descr->d_base = base;
        descr->d_wrapped = wrapped;
之后便将该tuple插入了tp_dict。
        到此,完成了275页图12-8的下半部分。
        为了可以匹配上那张图,我打开了listobject.c文件,找到了其中的tp_as_mapping域,该值为&list_as_mapping,是一个PyMappingMethods类型:
static PyMappingMethods list_as_mapping = {
    (lenfunc)list_length,
    (binaryfunc)list_subscript,
    (objobjargproc)list_ass_subscript
};
它所指的正是图中标出的list_subscript!其中的各个域都是在该文件中实现的函数
        另外,在对slotdefs数组进行初始化时,其中定义了许多宏:
#define MPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
    ETSLOT(NAME, as_mapping.SLOT, FUNCTION, WRAPPER, DOC)
#define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
    {NAME, offsetof(PyHeapTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \
     PyDoc_STR(DOC)}
以上的宏在初始化slotdefs中有:
    MPSLOT("__getitem__", mp_subscript, slot_mp_subscript,
           wrap_binaryfunc,
           "x.__getitem__(y) <==> x[y]"),
    通过其中的MPSLOT以及ETSLOT宏找到其中的操作操作相对于PyHeapTypeObject的偏移,从而将值存储到了slotdef的offset处
        这样,之前通过该offset所取得的函数就可以通过该offset重新获取该函数,顺便可以利用offset的大小进行排序。所以,从这里来看,PyHeapTypeObject可以看作是一块大的函数指针聚集。它的第一项可以容纳任何类型的PyObject对象,它主要用于class的创建,初始化时将各种方法什么的统一放到它的下面的域中,可以看作是对一个PyObject对象的暂时的包装。
0 0
原创粉丝点击