Closures in metaclasses

Falcolas garrickp at
Thu Jan 21 19:37:47 CET 2010

On Jan 21, 11:24 am, Arnaud Delobelle <arno... at> wrote:
> Falcolas <garri... at> writes:
> > I'm running into an issue with closures in metaclasses - that is, if I
> > create a function with a closure in a metaclass, the closure appears
> > to be lost when I access the final class. I end up getting the text
> > 'param' instead of the actual tags I am expecting:
> > ALL_TAGS =  ['a', 'abbr', 'acronym', 'address', 'applet', 'b', 'bdo',
> > 'big'] #snip
> > def _tag_meta(name, bases, dict_):
> >     for tag in ALL_TAGS:
> >         def generic_tag(*args, **kwargs):
> >             return Tag._generate_tag(tag, *args, **kwargs)
> >         #generic_tag = eval("lambda *args, **kwargs: Tag._generate_tag
> > ('%s', *args, **kwargs)" % tag)
> >         dict_[tag] = staticmethod(generic_tag)
> >     return type(name, bases, dict_)
> This is almost a FAQ and has nothing to do with metaclasses.  The
> simplest solution usually involves adding a default argument 'tag=tag'
> to the function you define (here, generic_tag), but you can't do this
> here because you have a **kwargs argument.  Instead, you can use a
> closure and do this for example:
> def factory(tag):
>     def generic_tag(*args, **kwargs):
>         return Tag._generate_tag(tag, *args, **kwargs)
>     return generic_tag
> def _tag_meta(name, bases, dict_):
>     for tag in ALL_TAGS:
>         dict_[tag] = staticmethod(factory(tag))
>     return type(name, bases, dict_)

I see - I was thinking it would preserve the closure from the for
statement, but I can see now why that would be wrong.

> However, I am usure about why you are using a metaclass.
> --
> Arnaud

It was the easiest way I found to add a lot of static methods to the
Tag class without writing each one out. __getattr__ was not working
for this application. This is for a very simple application, and I
didn't want to add a lot of complexity to it's use. I'm always open
for other options OTOH.

More information about the Python-list mailing list