Re: exec and closures

2008-02-21 Thread alitosis
On Feb 22, 3:18 am, Peter Otten <[EMAIL PROTECTED]> wrote:
> Alejandro Dubrovsky wrote:
> > 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
>
>
[snip]
> > 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

That works!  Excellent, thanks.
I still don't understand why the original doesn't work.  I thought
exec with no namespace specified used the current context, in which
_init_ would be _init_ already.  But understanding can wait.
ale

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: exec and closures

2008-02-21 Thread Peter Otten
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
-- 
http://mail.python.org/mailman/listinfo/python-list

exec and closures

2008-02-21 Thread Alejandro Dubrovsky
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?

Thanks,
ale
-- 
http://mail.python.org/mailman/listinfo/python-list