我通过猜测、检查和研究得出了一个解决方案。您几乎可以按照我在问题中提出的建议进行操作:复制函数对象并替换其__globals__
属性。
我使用的是Python 3,所以这里是一个修改版本answer对于上面链接的问题,添加了一个覆盖全局变量的选项:
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__)
The __globals__
属性是只读的,这就是为什么它必须传递给构造函数FunctionType
. The __globals__
无法更改现有函数对象的引用。
后记
我已经使用它足够多次了,现在它已在我编写和维护的实用程序库中实现,称为haggis
. See haggis.objects.copy_func.