繁体   English   中英

如何在python中修改本地命名空间

[英]How to modify the local namespace in python

如何在python中修改函数的本地命名空间? 我知道locals()在它内部调用时返回函数的本地命名空间,但是我想做这样的事情(我有理由为什么我要这样做,其中g不能被f访问,但它更快给出一个琐碎,愚蠢的例子来说明问题):

def g():
   pass

def f():
    g()

f.add_to_locals({'g':g})

你有几个选择。 首先,请注意,您的示例中的g实际上并不是函数的本地(即未在其中分配),它是全局的(即尚未分配给局部变量)。 这意味着它将在函数定义的模块中查找。这是幸运的,因为没有办法在外部修改本地(没有修补字节码),因为它们在函数运行时被分配,而不是之前。

一种选择是将函数注入函数模块的命名空间。 这将起作用,但会影响该模块中访问变量的每个函数,而不仅仅是一个函数。

要仅影响一个函数,您需要将func_globals指向其他位置。 不幸的是,这是一个只读属性,但您可以通过使用相同的主体重新创建函数来执行您想要的操作,但是可以使用不同的全局命名空间:

import new
f = new.function(f.func_code, {'g': my_g_function}, f.func_name, f.func_defaults, f.func_closure)

f现在将是缩进的,除了它将在提供的字典中查找全局变量。 请注意,这会重新绑定整个全局命名空间 - 如果f 确实存在变量,请确保您也提供它们。 这也是相当hacky,并且可能不适用于除pypy之外的python版本。

由于未调用该函数,因此它没有“本地”堆栈帧。 最简单的解决方案是使用全局上下文:

handler = None
def f():
    handler()

def g(): pass

handler = g

或者你可以在函数对象上设置g:

f.g = g

但我不确定如何从函数本身中获取函数对象。 如果它是一种方法,你会使用self

为什么不直接向f()添加一个参数并传递对g()的引用?

def g():
    pass

def f(func):
    func()

f(g)

我认为你可以从完全不同的角度解决问题。
功能是对象,带有词典; 因此,您可以将g添加到f,并使用它:

def g():
   print "g"

def f():
    f.g()

f.g = g

我假设您要这样做,因为函数f不是由您定义的,而是由其他模块定义的。 所以你想改变f()的工作方式。 特别是,您希望更改调用g时调用的内容。

所以我建议这个:

import thirdpartypackage

def mynewg():
   pass

thirdpartypackage.g = mynewg

这将更改模块thirdpartypackage的全局g。 因此,当调用thirdpartypackage.f()时,它将调用mynewg()而不是g()。

如果这不能解决它,可能g()实际上是从f()或somthing导入的。 然后解决方案是这样的:

import thirdpartypackage

def mynewg():
   pass

deg mynewf():
   mynewg()

thirdpartypackage.f = mynewf

也就是说,你完全使用你想要它的修改版本覆盖f()。

没有执行的函数没有任何本地人; 运行该函数时会创建本地上下文,并在它退出时销毁,因此没有“本地名称空间”可以从函数外部进行修改。

不过你可以这样做:

def f():
    g = [1]
    def func():
        print g[0]
    return func, g

f, val = f()
f()
val[0] = 2
f()

这使用数组来模拟引用。

这似乎有效

def add_to_locals(l):
    l['newlocal'] = 1

add_to_locals(locals())
assert newlocal

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM