The Don Beaudry/Jim Fulton hack
Dave Abrahams
abrahams at mediaone.net
Thu Dec 30 06:50:29 EST 1999
Hi,
I've recently been crawling through the source code (trying to understand
what all those fields in PyTypeObject really do), and stumbled across an
explanation for what I had read about being able to subclass a type
extension in Python: there's special code to make this possible!
Looking at the comment and code which follows...
/* Call the base's *type*, if it is callable.
This code is a hook for Donald Beaudry's
and Jim Fulton's type extensions. In
unexended Python it will never be triggered
since its types are not callable.
Ditto: call the bases's *class*, if it has
one. This makes the same thing possible
without writing C code. A true meta-object
protocol! */
PyObject *basetype = (PyObject *)base->ob_type;
PyObject *callable = NULL;
if (PyCallable_Check(basetype))
callable = basetype;
else
callable = PyObject_GetAttrString(
base, "__class__");
if (callable) {
PyObject *args;
PyObject *newclass = NULL;
args = Py_BuildValue(
"(OOO)", name, bases, methods);
if (args != NULL) {
newclass = PyEval_CallObject(
callable, args);
I think: it would be cool to experiment with this before writing any C code,
just to make sure I understand it. So I fire up Python. Since the special
code is never entered if the base is a real class (not shown), I figure it
has to be an instance: otherwise, how could it have an attribute called
"__class__"?
>>> class Empty: pass
...
>>> base = Empty()
>>> base.__class__ = stupid_class
Traceback (innermost last):
File "<input>", line 1, in ?
TypeError: __class__ must be set to a class
>>>
But as you can see, you can't set the __class__ attribute of an instance to
anything other than a class. So what have I missed? How am I supposed to get
this to work "without writing C code"?
Finally, another point. It is now possible to make extension classes which
walk, talk, and smell just like built-in classes except for one important
detail: as far as I can tell, there's no way to make is_instance work so
that it returns TRUE for base classes. In other words, if I have an
extension type "A" which is a "subclass" of another extension type "B", and
an instance of "A", "a", is_instance(a, B) should be true. I don't think
ther's any way to do that without a change to the Python source.
-Dave
More information about the Python-list
mailing list