By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,222 Members | 2,478 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,222 IT Pros & Developers. It's quick & easy.

About Michele Simionato's "classinitializer" decorator

P: n/a
Hi all.
I just send this post as a comment to the third part of Michele
Simionato's article about metaprogramming techniques at:

http://www.ibm.com/developerworks/li...GX03&S_CMP=ART
I found extremely useful the classinitializer "trick". I was thinking
over the caveat not to call a class initializer after the _metaclass_
hook (an exception being raised in that case).
Am I wrong if I state there's a plain solution to this ? I modified the
lines involving "type", replacing it with a custom meta type returned by
a call to frame.f_locals.get("__metaclass__", type), in such a way the
creation of the class involves the right metaclas, even if it was
defined just before the initializer function:

def classinitializer(proc):
# basic idea stolen from zope.interface.advice, P.J. Eby
def newproc(*args, **kw):
frame = sys._getframe(1)
if '__module__' in frame.f_locals and not \
'__module__' in frame.f_code.co_varnames: # we are in a class
thetype = frame.f_locals.get("__metaclass__", type)
def makecls(name, bases, dic):
try:
cls = thetype(name, bases, dic)
except TypeError, e:
if "can't have only classic bases" in str(e):
cls = thetype(name, bases + (object,), dic)
else: # other strange errs, e.g. __slots__ conflicts
raise
proc(cls, *args, **kw)
return cls
frame.f_locals["__metaclass__"] = makecls
else:
proc(*args, **kw)
newproc.__name__ = proc.__name__
newproc.__module__ = proc.__module__
newproc.__doc__ = proc.__doc__
newproc.__dict__ = proc.__dict__
return newproc

This makes the trick work even if a metaclass or another
classinitializer was defined first:

@classinitializer
def enhance(cls, **kw):
for k, v in kw.iteritems():
setattr(cls, k, v)

class M(type):
pass

class A:
__metaclass__ = M
enhance(x=100)
enhance(y=200)

>>A.x
100
>>A.y
200
>>type(A)
<class '__main__.M'>

What do you think about this solution ?

Diego Novella.
Jun 27 '08 #1
Share this Question
Share on Google+
2 Replies


P: n/a
On May 26, 7:10 pm, imho <ce...@comeno.itwrote:
Hi all.
I just send this post as a comment to the third part of Michele
Simionato's article about metaprogramming techniques at:

http://www.ibm.com/developerworks/li...a3.html?S_TACT...

I found extremely useful the classinitializer "trick".
I never use it. Too clever. I am waiting for class decorators
in Python 2.6.
I was thinking
over the caveat not to call a class initializer after the _metaclass_
hook (an exception being raised in that case).
Am I wrong if I state there's a plain solution to this ?
I think your solution is fine. Still, consider waiting for
class decorators ;)

Michele Simionato

Jun 27 '08 #2

P: n/a
Michele Simionato ha scritto:
On May 26, 7:10 pm, imho <ce...@comeno.itwrote:
>Hi all.
I just send this post as a comment to the third part of Michele
Simionato's article about metaprogramming techniques at:

http://www.ibm.com/developerworks/li...a3.html?S_TACT...

I found extremely useful the classinitializer "trick".

I never use it. Too clever. I am waiting for class decorators
in Python 2.6.
Uhm... I suspected that :-)
>I was thinking
over the caveat not to call a class initializer after the _metaclass_
hook (an exception being raised in that case).
Am I wrong if I state there's a plain solution to this ?

I think your solution is fine. Still, consider waiting for
class decorators ;)

Michele Simionato
Of course, I stand waiting here :-)

Thanks, Diego.

Jun 27 '08 #3

This discussion thread is closed

Replies have been disabled for this discussion.