namespaces and eval

George Sakkis george.sakkis at gmail.com
Tue May 20 23:36:07 EDT 2008


On May 16, 5:02 pm, Arnaud Delobelle <arno... at googlemail.com> wrote:
> dave.g1... at gmail.com writes:
> > Sorry for the repost, didnt' quite finish
>
> > Suppose I have a function in module X that calls eval e.g,
>
> > X.py
> > _______
> > Def foo(bar):
> >         Eval(bar)
> > _______
>
> > Now eval will be called using the default eval(bar,globals(),locals())
> > and globals will pull in anything in module X.
>
> > Now I have module Y that calls bar like so
> > Y.py
> > ________
> > from x import *
> > def biz():
> >         print "Im a silly example!"
> > Foo("biz()")
> > _______
>
> > Python will complain that it cannot find biz because it's not the X
> > module.
>
> > My question - is there any way to a) get a listing of active namespaes
> > search ALL active namespaces for a particular variable
>
> sys.modules gives you all the live modules.
>
> > b) get the namespace of the caller withing passing it in (here, Y)
>
> sys._getframe(1).f_globals (resp. sys._getframe(1).f_locals) gives you
> the caller's globals (resp. locals).
>
> > c) do anything else to get biz without passing
> > foo("biz()",locals(),globals()) or hacking biz into the __builtin__
> > namespace(don't know if it's even possible, but it defeats the
> > purpose of what I'm trying to do) ?
>
> Functions in Python are objects like any other, and can be passed as
> parameters.  I.e:
>
> x.py
> ----------
> def foo(bar):
>     bar()
>
>
>
>
>
> >>> from x import foo
> >>> def biz(): print "Boo!"
> >>> foo(biz)
> Boo!
>
> > I realize this is here for a reason, but I'm working on something
> > that's kind of a hack already
>
> > Thanks
> > dave
>
> > More gratuitous context. Long story I'm trying to write a hack for a
> > concise way of adding arbitrary methods to objects for JPA/JQuery like
> > chaning eg.
>
> > def foo(self):
> >     print "foo"
> >     return self;
>
> > wrap(x).foo().foo().foo().foo() etc....
>
> What about a composition function instead? I.e.
>
> compose(foo, foo, foo, foo)(x)
>
> Here's one that I made earlier:http://www.marooned.org.uk/~arno/python/compose.html

Neat, although the order is counter-intuitive; the callables should
better be called in the same order they are given in compose(). Here's
yet another take on the composition syntax:

DONE = object()

class Chainable(object):
    def __init__(self, val):
        self.val = val
    def __or__(self, func):
        if func is DONE:
            return self.val
        self.val = func(self.val)
        return self

# Test
def double(x): return 2*x
def square(x): return x**2
def succ(x): return x+1

>>> print Composable(2) | float | succ | square | double | DONE
18.0

Admittedly 'DONE' is ugly but it's necessary to denote that the piping
ends and the final value (rather than the Composable wrapper) should
be returned. The OP's wrap class suffers from the same problem but it
masks it by overriding __getattr__ in an old-style class. If the class
is changed to new-style, it becomes more obvious that
wrap(x).foo().foo().foo().foo() returns the wrap object, not x.

George



More information about the Python-list mailing list