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

Ale*_*lex 6 python namespaces local

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

def g():
   pass

def f():
    g()

f.add_to_locals({'g':g})
Run Code Online (Sandbox Code Playgroud)

Bri*_*ian 9

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

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

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

import new
f = new.function(f.func_code, {'g': my_g_function}, f.func_name, f.func_defaults, f.func_closure)
Run Code Online (Sandbox Code Playgroud)

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

  • 我不知道这是不是"好"的代码,但它正是我想要的.我正在将一个代码库转换为另一个代码库,我希望能够从另一种语言模拟语言结构.另一种语言可以打包代码并在命名空间中添加或删除该代码.它可用于覆盖不同的功能.所以它像时尚一样操纵堆栈中的命名空间.这是我能找到的最接近的东西,可以让我有效地做到这一点.谢谢 (2认同)

Aar*_*lla 3

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

handler = None
def f():
    handler()

def g(): pass

handler = g
Run Code Online (Sandbox Code Playgroud)

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

f.g = g
Run Code Online (Sandbox Code Playgroud)

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