覆盖从其他模块导入的函数中的全局变量
假设我有两个模块:
py
value = 3
def x()
return value
b.py
from a import x
value = 4
我的目标是使用a.x
in的功能b
,但更改该函数返回的值。具体来说,即使我运行,value
也将其查找a
为全局名称的来源b.x()
。我基本上是在尝试创建功能对象的副本,该副本与之b.x
相同a.x
但用于b
获取其全局变量。是否有合理而直接的方法?
这是一个例子:
import a, b
print(a.x(), b.x())
结果是当前3 3
,但我希望如此3 4
。
我想出了两种可行的复杂方法,但是我对其中任何一种都不满意:
- 使用复制和粘贴
x
在模块中重新定义b
。真正的功能比显示的要复杂得多,因此这并不适合我。 - 定义一个可以传递给x的参数,仅使用模块的值即可:
def x(value): return value
这给我要避免的用户增加了负担,并不能真正解决问题。
有没有办法修改该函数以某种方式获取其全局变量的位置?
-
我已经通过猜测和检查以及研究的结合提出了一个解决方案。您几乎可以完全按照我在问题中的建议进行操作:复制函数对象并替换其
__globals__
属性。我正在使用Python
3,因此这是上面链接的问题的答案的修改后的版本,带有一个覆盖全局变量的附加选项:import copy import types import functools def copy_func(f, globals=None, module=None): """Based on https://stackoverflow.com/a/13503277/2988730 (@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
b.py
from a import x value = 4 x = copy_func(x, globals(), __name__)
该
__globals__
属性是只读的,因此必须将其传递给的构造函数FunctionType
。__globals__
现有功能对象的引用不能更改:为什么func
.__ globals__被记录为只读?。