How to dynamically change the local function namespace?

Note: this question assumes Python 2.7.3.

I am looking for a sensible approach to dynamically changing the local function namespace, preferably in a way that adds the least mess to the body function.

What I mean will look something like this:

import os
from namespace_updater import update_locals

def somefunc(x, y, z):
    # ...
    # ...
    # this and that
    # ...
    # ...

    if os.environ.get('FROBNICATE'):
        from frobnitz import frobnicate
        update_locals(frobnicate(locals()))

    #
    # life goes on, possibly with duly frobnicated local variables...
    # ...
    # ...
    # ...

Thank!


PS: Below are the approaches that do not work.

The most naive approach to this is something like:

locals().update(new_locals(locals())

... but the documentation forlocals() explicitly forbids relying on such a voodoo to change local variables, so please do not send this as an answer (unless you can make a great case to ignore the documentation warning).

Further on the naive scale there is something like

for k, v in new_locals(locals()).items():
    exec ('%s = v' % k)

AFAICT, " " (.. ), . , exec ('%s = v' % k) .

" ", ", - exec ('%s = v' % k) ". ? , script . : (1) , ; (2) # 18; (3) # 15 18 (.. ). (2) (3) script. 50- (1). , - exec ('%s = v' % k). , script ( python 2.7), , , , , , exec ('%s = v' % k) .

x = 'global x'                            # 01
y = 'global y'                            # 02
def main():                               # 03
    x = 'local x'                         # 04
    y = 'local y'                         # 05
    run(locals())                         # 06
    print 'OK'                            # 07
    return 0                              # 08
                                          # 09
def run(namespace):                       # 10
    global y                              # 11
    print locals().keys()                 # 12
    for k, v in namespace.items():        # 13
        print '%s <- %r' % (k, v)         # 14
        exec ('%s = v' % k) #in locals()  # 15
    print locals().keys()                 # 16
    x = x                                 # 17
    #z = lambda: k                        # 18
    print x                               # 19
    print y                               # 20
                                          # 21
exit(main())                              # 22
+3
3

, , , .

def process(**kw):
  mycode = """\
print 'Value of foo is %s' % (foo,)
print 'Value of bar is %s' % (bar,)
"""
  exec mycode in kw

vars = {'foo': 2, 'bar': 3}
process(**vars)

. , " " , , , exec. .

, decorator module exec @decorator , , . , exec Python, eval.

. mycode - , , kw, , , , locals() .

def process(**kw):
  print 'Value of foo is %s' % (kw['foo'],)
  print 'Value of bar is %s' % (kw['bar'],)

process(foo=2, bar=3)
+1

-

def foo():
    print(x)

foo.__globals__["x"] = "Hello Python"

foo()

, , varible

def foo(flag):
    x = "Hello World"
    if flag:
        foo.__globals__["x"] = "Hello Python"

    print(x)

Hello World True False

0

Not sure if this is possible only when using an external function. I created a snippet:

def get_module_prefix(mod, localsDict):
    for name, value in localsDict.iteritems():
        if value == mod:
            return name
    raise Exception("Not found")

def get_new_locals(mod, localsDict):
    modulePrefix = get_module_prefix(mod, localsDict)
    stmts = []
    for name in dir(mod):
        if name.startswith('_'):
            continue
        if name not in localsDict:
            continue
        stmts.append("%s = %s.%s" % (name, modulePrefix, name))
    return "\n".join(stmts)

def func(someName):
    from some.dotted.prefix import some.dotted.name
    #here we update locals
    exec(get_new_locals(some.dotted.name, "some.dotted.name", locals()))
    print locals()
    print someName # value taken from aModule instead of parameter value


func(5)

Where:

  • get_module_prefix used to search for the name under which the module is imported,
  • get_new_locals returns assignment operators that can be used to update locales,

The actual update of the locales is performed on the line exec(get_new_locals(some.dotted.name, locals()))where we simply execute the assignment operators, in which we assign the values ​​from the module to local variables.

I am not sure if this is what you are actually doing.

0
source

All Articles