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

如何在python中修改本地名称空间,python,namespaces,local,Python,Namespaces,Local,如何在python中修改函数的本地名称空间?我知道locals()在函数内部调用时会返回函数的本地名称空间,但我想这样做(我有一个原因,为什么我想在f无法访问g的情况下执行此操作,但给出一个简单、愚蠢的示例来说明问题会更快): 由于没有调用该函数,因此它还没有“本地”堆栈帧。最简单的解决方案是使用全局上下文: handler = None def f(): handler() def g(): pass handler = g 或者可以在函数对象上设置g: f.g = g 但我不

如何在python中修改函数的本地名称空间?我知道locals()在函数内部调用时会返回函数的本地名称空间,但我想这样做(我有一个原因,为什么我想在f无法访问g的情况下执行此操作,但给出一个简单、愚蠢的示例来说明问题会更快):


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

handler = None
def f():
    handler()

def g(): pass

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

f.g = g

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

一个没有执行的函数,它没有任何局部变量;本地上下文在运行函数时创建,在退出时销毁,因此没有“本地命名空间”可从函数外部修改

不过,您可以这样做:

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

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

这使用数组来模拟引用。

我认为您可以从完全不同的角度解决这个问题。
函数是对象,带有它们的字典;因此,您可以将g添加到f中,并使用它:

def g():
   print "g"

def f():
    f.g()

f.g = g

为什么不在
f()
中添加一个参数,并传递对
g()
的引用呢


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

因此,我建议:

import thirdpartypackage

def mynewg():
   pass

thirdpartypackage.g = mynewg
这将更改模块第三方包的全局g。因此,现在调用thirdpartypackage.f()时,它将调用mynewg()而不是g()

如果这不能解决这个问题,那么可能g()实际上是从withing f()导入的,或者类似的东西。那么解决办法是:

import thirdpartypackage

def mynewg():
   pass

deg mynewf():
   mynewg()

thirdpartypackage.f = mynewf

也就是说,您可以使用一个经过修改的版本来完全覆盖f()。

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

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

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

import new
f = new.function(f.func_code, {'g': my_g_function}, f.func_name, f.func_defaults, f.func_closure)
f现在将是一致的,只是它将在提供的dict中查找全局变量。请注意,这将重新绑定整个全局名称空间-如果存在f确实查找的变量,请确保也提供它们。不过,这也相当粗糙,除了cpython之外,它可能不适用于其他版本的python。

这似乎是可行的

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

add_to_locals(locals())
assert newlocal

使用这种奇怪的技术,你的最终目标是什么?为什么不能先定义g(),再定义f()?我以前曾试图在运行时处理函数的名称空间(用于测试/模拟),但失败了。。。仅供参考。
add\u to\u locals
到底是什么?对我来说它似乎不存在<代码>属性错误:“函数”对象没有属性“添加到本地变量”@CharlieParker它不存在。这就是他试图实现的/询问是否有解决方案可以做到的。您是否成功地实现了这一点?如果确实想在函数中使用函数对象,可以使用inspect:import inspect import-pprint def fn():frame=inspect.currentframe()print frame.f_globals[frame.f_code.co_name].g fn.g='hello'fn()对于类函数、嵌套函数/闭包、lambda和任何修饰的函数来说,这都是错误的——它将返回装饰器的包装函数,而不是实际的函数。如果
f
是类/实例方法呢?这只适用于全局函数;无法从f中可靠地访问f。您能扩展它吗?Python函数是对象,如果是局部的或全局的,则没有区别-除非你指的是方法,但这是一个完全不同的故事,而不是OP所要求的。如果
f
是类/实例方法呢?这个网站应该真的需要解释-1票,所以人们不能无缘无故匿名投票否决正确答案。我不知道如果这是“好的”代码,但这正是我想要的。我正在将一个代码库转换为另一个代码库,我希望能够模拟来自另一种语言的语言构造。另一种语言可以打包代码,并从命名空间中添加或删除该代码。它在重写不同函数时非常有用。因此它可以像fa一样在堆栈中操纵命名空间shion。这是我能找到的最能让我高效完成这项工作的东西。谢谢这
new
库是什么?它在函数内部不起作用。它不会向命名空间添加值。
import new
f = new.function(f.func_code, {'g': my_g_function}, f.func_name, f.func_defaults, f.func_closure)
def add_to_locals(l):
    l['newlocal'] = 1

add_to_locals(locals())
assert newlocal