在初始化中,调用
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里面
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;
}