Strange metaclass behaviour
Christian Eder
chris.eder at gmx.at
Thu Mar 23 13:30:22 EST 2006
Michele Simionato wrote:
> Still, it is an interesting exercise if you are willing to risk the
> melting of your brain,
> so here is the code ;)
I tried your code and it fixes the double execution, but the __new__ is
executed in context of M_A instead of M_B which would be the more
specific type here.
Anyway, I think I found an acceptable solution for the problem.
The question is "What Do I need to fix metaclasses ?"
And the answer, of course, is "a meta-meta-class !"
The following code solves the problem.
It's basically Ziga's code except that I added one level of abstraction
(to avoid adding this kludge code to each custom metaclasses'es __new__):
class _fixed_type_ (type) :
def __call__ (meta, name, bases, dict) :
meta = meta._get_meta (bases, dict)
cls = meta.__new__ (meta, name, bases, dict)
meta.__init__ (cls, name, bases, dict)
return cls
# end def __call__
def _get_meta (meta, bases, dict) :
if "__metaclass__" in dict :
return dict ["__metaclass__"]
winner = meta
for b in bases :
cand = type (b)
if cand in (types.ClassType, type) :
pass
elif issubclass (cand, winner) :
winner = cand
elif issubclass (winner, cand) :
pass
else :
raise TypeError ("Metatype conflict among bases")
return winner
# end def _get_meta
# end class _fixed_type_
class my_type (type) :
__metaclass__ = _fixed_type_ ### to fix metaclasses, we need
### meta-meta classes
# end class my_type
Then I made "my_type" the root of my metaclass hierarchy
(instead of "type") which solves all my problems.
After 5 years of Python, I still find it impressive how much
vodoo and mojo one can do here :-)
regards
chris
More information about the Python-list
mailing list