Mehrdad Mehrdad - 4 months ago 8
Python Question

How to bind a name statically (lexically) in Python?

Consider this code:

class Bar(object): pass

class Foo(object):
def bar(self): return Bar()

f = Foo()
def Bar(): pass
print(f.bar())


It prints
None
. But the poor guy
bar
didn't expect
Bar
to be what it became afterward!

My question is, what is the "best" (most elegant, most efficient, most Pythonic, whatever) code I can write inside of
Foo
(hopefully without polluting outside scopes) that will make sure
bar
can reference the
Bar
that was defined at the time of its declaration rather than invocation?

(It's not that I can't come up with any solutions, but rather it's that I don't know what the proper solution is.)

Answer

Answering my own question, but the answer is to put everything in a closure:

def static_define(locals, super, tuple):  # All arguments are bound STATICALLY
    # Anything defined here will be exported externally
    class Foo(tuple):
        def __new__(cls, *args):
            return super(Foo, cls).__new__(cls, args)
    return locals()

# The following line "exports" all the returned locals into the current global namespace
(lambda f, bi: (lambda g: g.pop(f.__name__) and bi.None or g.update((lambda args: (lambda l: bi.reduce(lambda l, v: l.pop(v, bi.None) and bi.None or l, args, l))(f(*bi.map(lambda v: bi.eval(v, g), args))))(bi.__import__('inspect').getargspec(f).args)))(f.__globals__))(static_define, __builtins__)

super = None  # tamper!
print Foo()   # unaffected by tampering
Comments