[Types-sig] Re: Meta-classes discussion starter
Just van Rossum
just@letterror.com
Wed, 2 Dec 1998 14:00:02 +0100
>> + PyDict_DelItemString(methods, "__class__");
At 10:31 AM +0100 12/2/98, M.-A. Lemburg wrote:
>I like the patch... but why do you delete the __class__ attribute ?
I must admit that the one aspect of the patch I am not quite confident about...
>To prevent endless recursion in some weird cases ?
No, merely from this view: while playing with the mechanism, I found myself
constantly deleting __class__ from the dict in Python. I could not find any
reason why I would ever need the __class__ entry. It's a little like this:
def somefunction(dict):
pass
mydict = {"foo": somefunction}
if mydict.has_key("foo"):
func = mydict["foo"]
func(mydict)
It just seemed silly to have __class__ still around, especially since I
cannot use it as a real attribute anyway: in instance can only have a Real
Class object as __class__ attribute. So in my experiments I used __klass__
to bind my fake class object to.
[ *** warning: the author is drifting *** ed. ]
*Maybe* it would be even cooler (in today's Python, maybe not 2.0) to use
__metaclass__ (or __turtle__, *whatever*) as the secret word, and have a
second GuidoHook that triggers with that same name *before* it checks for
__class__. Or for my part get rid of the __class__ check altogether. That
way it we could have even more control over classes. Right now, say I
define a little metaclass like this:
class MyMetaClass:
def __init__(self, name, bases, namesspace):
... etc.
Then I can create a "normal" class like this:
class MyClass:
__class__ = MyMetaClass
This invoked my hook. Then I subclass:
class MySecondClass(MyClass):
pass
This invokes Guido's hook, which will call MyMetaClass since that's
MyClass's *real* __class__ attribute, so MySecondClass will automatically
be an instance of MyMetaClass. Fine. Almost too perfect.
The caveat is this: Guido's Hook *requires* that __class__ is a real class
(well, no, sure it's not really the hook that forces this, but it's a side
effect of choosing the name __class__ as secret trigger) which means the
constructor of a class is *always* some __init__ func of a metaclass. Which
means we can't emulate the current Python object model in full since we
can't trap access to an "__init__" attr: it will always be found before any
__getattr__ func can get triggered... It really means that I cannot by
definition make this work correctly:
class MyClass:
__class__ = MyMetaClass
def __init__(self, a):
self.a = a
class MySecondClass(MyClass):
def __init__(self):
MyClass.__init__(self, 100)
The last line can't work because
- MyClass is in instance of MyMetaClass
- MyClass.__init__ will be found in MyMetaClass *before* it can trigger any
__getattr__ that could look it up inside MyClass.
It's not easy, but it could be made work with Today's Python had "we" not
chosen __class__ as the magic attribute for metahooks...
Just