Falcolas <garri...@gmail.com> 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_) Then your Tag example class will work as you expect: class Tag(object): __metaclass__ = _tag_meta @staticmethod def _generate_tag(tag_name, *args, **kwargs): # Does the expected, following is just for the example's sake return tag_name I am sure that there are plenty of discussions of this issue in the archives of c.l.python. I just can't think of a good keyword to google it ATM. However, I am usure about why you are using a metaclass. HTH -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list