[Python-Dev] Class Methods
Just van Rossum
just at letterror.com
Mon Apr 23 11:08:11 EDT 2001
Thomas Heller wrote:
>
> "Just van Rossum" <just at letterror.com> wrote ...
> > I once proposed (and implemented as an extension to the metaclass hook)
> > this:
> >
> > class Foo:
> > __class__ = WeirdClass
> >
> > I still don't think that's all that bad, especially since it screams
> > magic at you...
>
> Is your code available somewhere?
No, but I just found the patch in my archives. It's probably against 1.5.2,
so might not even apply to 2.x. I've pasted it below.
Just
- - - - - 8< - - - - - - - - - - - - -
*** ceval.c Tue Dec 1 05:44:30 1998
--- jmetapatch/ceval.c Tue Dec 1 05:44:12 1998
***************
*** 2672,2681 ****
--- 2672,2738 ----
if (!PyString_Check(name)) {
PyErr_SetString(PyExc_SystemError,
"build_class witn non-string name");
return NULL;
}
+ /* __BEGIN__ of Just's Hook
+
+ Guido's metahook is defined as follows:
+ - if one of the bases has a __class__ attribute (but is
+ itself not a class!), call that thing with (name,
+ bases, methods)
+ In addition I propose almost the opposite:
+ - if the "methods" dict (__dict__ from the Python
+ perspective) has a __class__ key, call that thing with
+ (name, bases, methods)
+
+ This means that metaclasses are not special anymore, and
+ you have to specify a metaclass *explicitly* to get meta
+ behaviour. Example:
+
+ class Foo:
+ __class__ = MyMetaClass
+
+ as apposed to
+
+ MyMeta = MyMetaClass("MyMeta", (), {})
+
+ class Foo(MyMeta): pass
+
+ as it is with Guido's hook.
+
+ Reasons for this new hook:
+ - Guido's hook abuses inheritance syntax, making it
+ impossible to inherit from metaclasses without special
+ trickery.
+ - implementing Meta stuff seems cleaner. Or maybe it's
+ just me...
+
+ At first I thought Guido's hook would not be compatible with
+ mine, but they work together beautifully: inheritance works
+ just like you would expect.
+ */
+ {
+ PyObject *callable = NULL;
+ callable = PyDict_GetItemString(methods, "__class__");
+ if (callable) {
+ PyObject *args;
+ PyObject *newclass = NULL;
+ PyDict_DelItemString(methods, "__class__");
+ args = Py_BuildValue(
+ "(OOO)", name, bases, methods);
+ if (args != NULL) {
+ newclass = PyEval_CallObject(
+ callable, args);
+ Py_DECREF(args);
+ }
+ return newclass;
+ } else {
+ PyErr_Clear();
+ }
+ }
+ /* __END__ of Just's Hook */
n = PyTuple_Size(bases);
for (i = 0; i < n; i++) {
PyObject *base = PyTuple_GET_ITEM(bases, i);
if (!PyClass_Check(base)) {
/* Call the base's *type*, if it is callable.
More information about the Python-list
mailing list