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.cstatic intadd_operators(PyTypeObject *type){... init_slotdefs();...}/* Initialize the slotdefs table by adding interned string objects for the names and sorting the entries. */static voidinit_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.cintPyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)