当前位置:编程学习 > 网站相关 >>

Python源码学习之初始化(二)

在初始化中,调用
void
_Py_ReadyTypes(void)
{
    if (PyType_Ready(&PyType_Type) < 0)
        Py_FatalError("Can't initialize type type");

    if (PyType_Ready(&_PyWeakref_RefType) < 0)
        Py_FatalError("Can't initialize weakref type");
	...
}
对各种数据类型的定义做初始化

来看
int PyType_Ready(PyTypeObject *type)的定义,
它把传入的type的tp_base用&PyBaseObject_Type初始化

	...
    /* Initialize tp_base (defaults to BaseObject unless that's us) */
    base = type->tp_base;
    if (base == NULL && type != &PyBaseObject_Type) {
        base = type->tp_base = &PyBaseObject_Type;
        Py_INCREF(base);
    }

    /* Now the only way base can still be NULL is if type is
     * &PyBaseObject_Type.
     */

    /* Initialize the base class */
    if (base != NULL && base->tp_dict == NULL) {
        if (PyType_Ready(base) < 0)   //有点递归的意思
            goto error;
    }
	...
	
	
接着初始化其他成员变量

    /* Initialize tp_bases */
    bases = type->tp_bases;
    if (bases == NULL) {
        if (base == NULL)
            bases = PyTuple_New(0);
        else
            bases = PyTuple_Pack(1, base);
        if (bases == NULL)
            goto error;
        type->tp_bases = bases;
    }

    /* Initialize tp_dict */
    dict = type->tp_dict;
    if (dict == NULL) {
        dict = PyDict_New();
        if (dict == NULL)
            goto error;
        type->tp_dict = dict;
    }
	
接着是一些内置function的初始化

	/* Add type-specific descriptors to tp_dict */
    if (add_operators(type) < 0)
        goto error;
    if (type->tp_methods != NULL) {
        if (add_methods(type, type->tp_methods) < 0)
            goto error;
    }
    if (type->tp_members != NULL) {
        if (add_members(type, type->tp_members) < 0)
            goto error;
    }
	
这里重点看一下add_operators in typeobject.c

static int
add_operators(PyTypeObject *type)
{
	...
    init_slotdefs();
	...
}

/* Initialize the slotdefs table by adding interned string objects for the
   names and sorting the entries. */
static void
init_slotdefs(void)
{
    slotdef *p;
    static int initialized = 0;

    if (initialized)
        return;
    for (p = slotdefs; p->name; p++) {
        p->name_strobj = PyUnicode_InternFromString(p->name);
        if (!p->name_strobj)
            Py_FatalError("Out of memory interning slotdef names");
    }
    qsort((void *)slotdefs, (size_t)(p-slotdefs), sizeof(slotdef),
          slotdef_cmp);
    initialized = 1;
}

//这里是我们在python编程中经常重载的一些函数的列表
static slotdef slotdefs[] = {
    SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc,
           "x.__len__() <==> len(x)"),
    SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc,
      "x.__add__(y) <==> x+y"),
    SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item,
           "x.__getitem__(y) <==> x[y]"),
	...
}

    SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc,
           "x.__len__() <==> len(x)")
	
	#define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
    ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER, DOC)
	
	等价
	ETSLOT("__len__", as_sequence.sq_length, slot_sq_length, wrap_lenfunc, "x.__len__() <==> len(x)")
	
	#define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
    {NAME, offsetof(PyHeapTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \
     PyDoc_STR(DOC)}
	 
	等价
	
	{"__len__", offsetof(PyHeapTypeObject, as_sequence.sq_length), (void*)slot_sq_length, wrap_lenfunc, PyDoc_STR("x.__len__() <==> len(x)")}
	
	而
	typedef struct wrapperbase slotdef;
	struct wrapperbase {
    char *name;
    int offset;
    void *function;
    wrapperfunc wrapper;
    char *doc;
    int flags;
    PyObject *name_strobj;
	};
	
	
	于是上面的宏定义展开为
	{	"__len__",    /* name */
		offsetof(PyHeapTypeObject,  /* offset* /
		as_sequence.sq_length),  
		(void*)slot_sq_length, 		/* void *function */
		wrap_lenfunc,      /* wrapper */
		PyDoc_STR("x.__len__() <==> len(x)") /* char *doc */
	}
	
新建一个module的时候,总会调用,而
PyDict_SetItemString(m->md_dict, "__name__", nameobj)  这个函数会向字典里面加一个item,
于是我们可以在python启动以后写 xxxx.__name__,  xxx.__doc__
PyObject *
PyModule_New(const char *name)
{
    PyModuleObject *m;
    PyObject *nameobj;
    m = PyObject_GC_New(PyModuleObject, &PyModule_Type);
    if (m == NULL)
        return NULL;
    m->md_def = NULL;
    m->md_state = NULL;
    nameobj = PyUnicode_FromString(name);
    m->md_dict = PyDict_New();
    if (m->md_dict == NULL || nameobj == NULL)
        goto fail;
    if (PyDict_SetItemString(m->md_dict, "__name__", nameobj) != 0)
        goto fail;
    if (PyDict_SetItemString(m->md_dict, "__doc__", Py_None) != 0)
        goto fail;
    if (PyDict_SetItemString(m->md_dict, "__package__", Py_None) != 0)
        goto fail;
    Py_DECREF(nameobj);
    PyObject_GC_Track(m);
    return (PyObject *)m;

 fail:
    Py_XDECREF(nameobj);
    Py_DECREF(m);
    return NULL;
}

当我们在命令行输入任何command的时候,都会调用pythonrun.c
int
PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)


 

在PyTypeObject初始化中,add_xxxx 是操作该object的tp_dict,把每一个operator, method,member定义都以key-value的形势放到tp_dict里面
<span style="white-space:pre">	</span>if (add_operators(type) < 0)
        goto error;
    if (type->tp_methods != NULL) {
        if (add_methods(type, type->tp_methods) < 0)
            goto error;
    }
    if (type->tp_members != NULL) {
        if (add_members(type, type->tp_members) < 0)
            goto error;
    }
    if (type->tp_getset != NULL) {
        if (add_getset(type, type->tp_getset) < 0)
            goto error;
    }

 

补充:Web开发 , Python ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,