[Python-3000] A better way to initialize PyTypeObject
Talin
talin at acm.org
Tue Nov 28 10:22:07 CET 2006
More on the 'cruft removal' topic:
I notice that a number of fields in PyTypeObject are deprecated; the
question is, how to get rid of them without gratuitously breaking
everything? Even if there's zero code out there that still uses
tp_getattr instead of tp_getattro, you can't simply remove the field
because it takes up a placeholder slot in the C initializer list.
Has anyone proposed the notion of getting away from C-style initializer
lists, at least for the case of PyTypeObject?
For example, consider the case for tp_init and tp_new. Currently these
are filled in with the C initializer list for PyTypeObject. Because
these are the 38th and 40th fields in PyTypeObject, you have to put 37
initializer values before them, whether you use them or not.
Instead of doing that, however, you could put them in the method table,
tp_methods:
static PyMethodDef Noddy_methods[] = {
{ SPECMETH_NEW, (PyCFunction)Noddy_new, METH_VARARGS, "..." },
{ SPECMETH_INIT, (PyCFunction)Noddy_init, METH_VARARGS, "..." },
{ NULL } /* Sentinel */
};
'SPECMETH_NEW' and 'SPECMETH_INIT' are sentinel values indicating that
these are 'special' methods, which are ignored during the normal
scanning of this table. Instead, when the type is initialized, the
method table is scanned for these special methods, and the corresponding
field in PyTypeObject is filled in with the method pointer. The same
holds true for all of the other special method pointers.
Now, you still have the problem that 'tp_methods' itself is something
like the 28th field in the struct, which means you still have all of
those empty fields to consider. So instead, make a new version of
PyType_Ready which takes an optional parameter of the method table for
the type, which is filled in as part of the initialization.
You could add another parameter for filling of data fields, which would
point to a similar table that would hold values for non-function
initializers.
What you end up with is code that looks like this:
PyTypeObject myType = {
PyObject_HEAD_INIT(NULL)
0,
"myType",
sizeof(myInstance)
}
void init() {
if (PyType_ReadyInit( &myType, myTypeMethods, myTypeData ) < 0)
return;
}
Note that this requires no change to the PyTypeObject struct itself, or
of any code that currently uses it - the only thing that changes is the
way that the struct's data fields are filled in.
What this would give you is a way to construct types that would be
immune to future revisions of the PyTypeObject struct; You could add,
remove, rename, or re-order the fields in the struct without breaking
existing code.
(If there's an existing proposal for this, feel free to post a
reference. I did look :)
-- Talin
More information about the Python-3000
mailing list