metaclass and customization with parameters

Gustavo Niemeyer niemeyer at
Tue Oct 5 23:57:49 CEST 2004

Hello Carlos,

> I'm not a metaclass expert, but I think I can share a few useful tips
> with you. I've been studying metaclasses lately, and I've fallen on
> some traps that seem to be common. I apologize if my tone sound
> pretentious at times -- my intention is probably better than my words.

Your description is really interesting and informative,
as usual. :-)

> >>> class MyClass:
> ... 	for i in range(10):
> ... 		def newmethod(self,i=i):
> ... 			print "I'm method #%d" % i
> ... 		newname = "method%d" % i
> ... 		locals()[newname] = newmethod
> ... 
> >>> mc = MyClass()
> >>> mc.method0()
> I'm method #0
> >>> mc.method1()
> I'm method #1
> Although it doesn't involve metaclasses at all, it shows how dynamic
> the class creation process is, and how much control one can have with
> it. There are two worthy comments to make:
> 1) the locals() dict is the key at this step of class creation. The
> local dict is one of the parameters passed to the metaclass. If you
> fill the locals() with values -- either manually, as in the example
> above, or by assigning values to local vars -- all the values will be
> part of the class definition.

As an interesting side effect, the class above will have
'newname', 'newmethod', and 'i' attributes, besides 'method0-9'.

> 2) the signature of "def newmethod(self,i=i)" shows another
> interesting side effect. The value if <i> (defined in the for loop) is
> passed as a keyword paramenter, and is evaluated whenever the 'def'
> statement is found. Because it changes, the def is re-run at every
> loop. In the lack of this hack, the def would run only at the first
> time, and all methods would in fact be the same.

That's not true. The def statement is rerun every loop, no matter
what parameters are used. One can check that by issuing:

print MyClass.method0.im_func
print MyClass.method1.im_func

Of course, in your example, not using the 'i=i' trick would be a
problem, since the 'i' variable is lost, and inside the method a
global is looked for, creating an error.

Gustavo Niemeyer

More information about the Python-list mailing list