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 ,