Mad*_*ist 4 python global-variables
假设我有两个模块:
a.py
value = 3
def x()
return value
Run Code Online (Sandbox Code Playgroud)
b.py
from a import x
value = 4
Run Code Online (Sandbox Code Playgroud)
我的目标是使用a.xin的功能b,但更改函数返回的值。具体来说,即使我运行,也会作为全局名称的来源value进行查找。我基本上试图创建函数对象的副本,该副本与该副本相同,但用于获取其全局变量。有没有一种相当简单的方法来做到这一点?ab.x()b.xa.xb
这是一个例子:
import a, b
print(a.x(), b.x())
Run Code Online (Sandbox Code Playgroud)
目前的结果是3 3,但我希望是这样3 4。
我想出了两种有效的复杂方法,但我对其中任何一种都不满意:
x在模块中重新定义。b真正的功能比显示的要复杂得多,所以这不适合我。定义一个可以传递给 x 的参数并仅使用模块的值:
def x(value):
return value
Run Code Online (Sandbox Code Playgroud)
这给用户增加了我想避免的负担,并没有真正解决问题。
有没有办法以某种方式修改函数获取全局变量的位置?
我通过猜测、检查和研究得出了一个解决方案。您几乎可以完全按照我在问题中提出的建议进行操作:复制函数对象并替换其__globals__属性。
我使用的是 Python 3,所以这里是上面链接问题的答案的修改版本,并添加了覆盖全局变量的选项:
import copy
import types
import functools
def copy_func(f, globals=None, module=None):
"""Based on /sf/answers/945229421/ (@unutbu)"""
if globals is None:
globals = f.__globals__
g = types.FunctionType(f.__code__, globals, name=f.__name__,
argdefs=f.__defaults__, closure=f.__closure__)
g = functools.update_wrapper(g, f)
if module is not None:
g.__module__ = module
g.__kwdefaults__ = copy.copy(f.__kwdefaults__)
return g
Run Code Online (Sandbox Code Playgroud)
b.py
from a import x
value = 4
x = copy_func(x, globals(), __name__)
Run Code Online (Sandbox Code Playgroud)
该__globals__属性是只读的,这就是为什么它必须传递给 的构造函数FunctionType。__globals__无法更改现有函数对象的引用。
后记
我已经使用它足够多次了,它已在我编写和维护的名为 的实用程序库中实现haggis。看haggis.objects.copy_func。