exec and closures
Peter Otten
__peter__ at web.de
Thu Feb 21 11:18:16 EST 2008
Alejandro Dubrovsky wrote:
> About a month ago, there was a thread on auto-assigning decorators for
> __init__. One by André Roberge is here:
> http://groups.google.com/group/comp.lang.python/browse_frm/
> thread/32b421bbe6caaeed/0bcd17b1fa4fb07c?#0bcd17b1fa4fb07c
>
> This works well for simple cases, but doesn't take keyword arguments or
> set default values. I wrote a more extensive version implementing python
> call semantics, but it seemed awkard to be repeating something the
> compiler does already, so I tried execing a function definition on the
> fly with the right parameters that would function as the decorator. Like
> this (adjust the indentation variable if it throws a syntax error)
>
> def autoassign(_init_):
> import inspect
> import functools
>
> argnames, _, _, defaults = inspect.getargspec(_init_)
> argnames = argnames[1:]
>
> indentation = ' '
> settings = ['self.%s = %s' % (arg[1:], arg) for arg in argnames
> if arg[0] == '_']
>
> if len(settings) <= 0:
> return _init_
>
> if defaults is None:
> args = argnames[:]
> else:
> args = argnames[:-len(defaults)]
> for key, value in zip(argnames[-len(defaults):],defaults):
> args.append('%s=%s' % (key, repr(value)))
>
> template = """def _autoassign(self, %(args)s):
> %(setting)s
> _init_(self, %(argnames)s)
> """ % {'args' : ", ".join(args), 'setting' : "\n".join(['%s%s' %
> (indentation, setting) for setting
> in settings]), 'argnames' : ', '.join(argnames)}
>
> try:
> exec template
> except SyntaxError, e:
> raise SyntaxError('%s. line: %s. offset %s:\n%s' %
> (e.msg, e.lineno, e.offset, template))
> return _autoassign
>
>
> Which creates what looked like the right template, but when instantiating
> a class that uses that (eg
> class A(object):
> @autoassign
> def __init__(self,_a):
> pass
> a = A(3)
>
> it throws a
> NameError: global name '_init_' is not defined
>
> Is there a way to bind the _init_ name at exec time?
Use a dedicated namespace:
namespace = dict(_init_=_init_)
exec template in namespace
return namespace["_autoassign"]
Peter
More information about the Python-list
mailing list