On Jan 21, 6:37 pm, Falcolas <garri...@gmail.com> wrote: > On Jan 21, 11:24 am, Arnaud Delobelle <arno...@googlemail.com> wrote: > > > > > > > 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_) > > 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. > > > HTH > > > -- > > 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.
This should work (untested): class Tag(object): @staticmethod def _generate_tag(tag_name, *args, **kwargs): # Does the expected, following is just for the example's sake return tag for tag in ALL_TAGS: setattr(Tag, tag, staticmethod(factory(tag))) Or you could override __getattr__ -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list