[Types-sig] Re: Meta-classes discussion starter
Just van Rossum
just@letterror.com
Tue, 1 Dec 1998 12:16:04 +0100
At 11:12 PM -0500 11/30/98, Barry A. Warsaw wrote:
>I haven't seen any comments on my posted syntax proposal; perhaps it's
>gross, but anyway I liked it. Or maybe because it's buried in a long
>egroups posting:
>
> <http://www.egroups.com/list/python-classes/54.html>
(Hm, since your post contains mostly code, and egroups screws it up
majorly, I cannot read it... If you still have it, I'd sure appreciate it
as prvt mail.)
> JvR> Which means you specify a metaclass like this:
>
> | class MyClass:
> | __class__ = MyMetaClass
>
> JvR> Not exactly pretty, but at least it doesn't look like
> JvR> inheritance. It also means that if you want to subclass from
> JvR> MyMetaClass you write
>
>Not exactly ugly either! Very similar to my proposal except 1) I
>chose __nature__ as the magic attribute, and 2) I didn't actually
>implement it like you did, just sort of modeled it in Python.
I initially chose __class__ just because Guido's hook uses that, too. Turns
out that because of that the two Brotherly Hooks complement each other
wonderfully!
> JvR> (If anyone wants
> JvR> to play, I could post a patch.)
>
>Yes, please do!
See below... It's a against the current state of Python 1.5.2b1. It should
be 100% compatible with the existing hooks (ie. I tried carefully not to
break things).
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.