Inferring initial locals()

George Sakkis george.sakkis at gmail.com
Thu Jun 21 23:35:16 CEST 2007


On Jun 21, 4:42 pm, "bruno.desthuilli... at gmail.com"
<bruno.desthuilli... at gmail.com> wrote:
> On Jun 21, 8:51 pm, George Sakkis <george.sak... at gmail.com> wrote:
>
>
>
> > I wonder if there is a (preferably not too-hackish) solution to the
> > following introspection problem: given a callable and a number of
> > positional and/or keyword arguments, infer what would be the frame's
> > locals() right after the function is called. For example, given:
>
> > def f(x, y=1, *a, **k):
> >     z = x + y
> >     w = len(a) - len (k)
> >     return z * w
>
> > I'd like to have a function
>
> > def get_init_locals(callable, *args, **kwds):
> >     # TODO
> >     pass
>
> > so that:
>
> > >>> get_init_locals(f, 3)
>
> > {'a': (), 'k': {}, 'x': 3, 'y': 1}
>
> You might be intersted in the 'inspect' module.

Turns out it wasn't that hard after all; I came up with the following:

import types, inspect
from itertools import islice, izip

def localsProber(callable):
    args, varargs, varkw, defaults = inspect.getargspec(callable)
    if defaults is None: defaults = ()
    # create a function with the same signature as the callable and
    # "return locals()" for body
    context = {'__builtins__': {'locals': locals}}
    iterargs = iter(args)
    # - first all the required args
    sig_args = list(islice(iterargs, len(args)-len(defaults)))
    # - then all the default args
    for arg,default in izip(iterargs,defaults):
        context[arg] = default
        sig_args.append('%s=%s' % (arg,arg))
    # - then variable positional and keyword args (if any)
    if varargs: sig_args.append('*' + varargs)
    if varkw: sig_args.append('**' + varkw)
    name = callable.__name__
    exec 'def %s(%s): return locals()' % (name, ', '.join(sig_args))
in context
    prober = context[name]
    if inspect.ismethod(callable): # return a method if callable is a
method
        prober = types.MethodType(prober, callable.im_self,
callable.im_class)
    return prober

>>> def f(x, y=1, *a, **k): pass
...
>>> get_f_locals = localsProber(f)

>>> get_f_locals(3)
{'a': (), 'k': {}, 'x': 3, 'y': 1}

>>> get_f_locals(3,4,5)
{'a': (5,), 'k': {}, 'x': 3, 'y': 4}

>>> get_f_locals(3,q=-1)
{'a': (), 'k': {'q': -1}, 'x': 3, 'y': 1}


George




More information about the Python-list mailing list