[英]How do I call globals() from another imported function in Python?
[英]Overload imported function that uses globals in Python
有点类似于带有导入的全局变量 -但带有函数。
说我有main_file.py
:
global main_var1, main_var2
main_var1 = ""
main_var2 = 0
def main():
for gkey, gval in sorted(globals().items()):
print(" mf_glb", gkey, "is", type(gval), "and is equal to ", gval)
for name in dir():
myvalue = eval(name)
print(" mf_dir", name, "is", type(myvalue), "and is equal to ", myvalue)
setup()
print("main_file says", main_var1, main_var2, " setup is " + str(eval("setup")))
def setup():
global main_var1, main_var2
main_var1 = "Initialized"
main_var2 = -123
if __name__ == "__main__":
main()
如果我直接运行main_file.py
,它将输出(按预期):
...
('main_file says', 'Initialized', -123, ' setup is <function setup at 0xb766d17c>')
现在说,我要使用main_file.py
所有其他main_file.py
(包括main()
函数); 但我想重载setup()
以便它设置不同的变量; 所以我尝试作为user_file.py
:
global main_var1, main_var2
for gkey, gval in sorted(globals().items()):
print(" uf1_glb", gkey, "is", type(gval), "and is equal to ", gval)
for name in dir():
myvalue = eval(name)
print(" uf1_dir", name, "is", type(myvalue), "and is equal to ", myvalue)
print()
from main_file import *
for gkey, gval in sorted(globals().items()):
print(" uf2_glb", gkey, "is", type(gval), "and is equal to ", gval)
for name in dir():
myvalue = eval(name)
print(" uf2_dir", name, "is", type(myvalue), "and is equal to ", myvalue)
print()
print("A: setup is " + str(eval("setup")))
def setup():
global main_var1, main_var2
main_var1 = "Overloaded"
main_var2 = 42
print("B: setup is " + str(eval("setup")))
main() # since main is not def'd in here (user_file), this will call the one from main_file
如果我使用python user_file.py
运行它, python user_file.py
得到类似以下内容的信息:
(' uf2_glb', 'setup', 'is', <type 'function'>, 'and is equal to ', <function setup at 0xb7709374>)
(' uf2_dir', 'setup', 'is', <type 'function'>, 'and is equal to ', <function setup at 0xb7709374>)
...
A: setup is <function setup at 0xb7709374>
B: setup is <function setup at 0xb7709a74>
...
(' mf_glb', 'setup', 'is', <type 'function'>, 'and is equal to ', <function setup at 0xb7709374>)
...
('main_file says', 'Initialized', -123, ' setup is <function setup at 0xb7709374>')
因此,基本上,我的重载setup()
处于0xb7709a74
,仅在user_file
更改; 而main_file
仍然使用旧setup()
在0xb7709374
,所以我的预期变化超载不打印。
在此从上面链接的问题答案具有从教程,说明一个副本:
实际上,模块中的全局变量仅仅是该模块的属性(即成员实体),类似于类变量在类中的角色。 当模块A导入模块B时,B的名称空间将复制到A的名称空间。 如果模块B具有全局变量X,则模块A将创建该名称的变量,其初始值是模块B在导入时具有该名称的变量的值。 但是其中一个模块对X的更改不会反映在另一个模块中。
因此,有没有办法从user_file
重载main_file
的功能? 事情可能会变得更加困难,因为setup()
实际上使用main_file
的全局变量来工作...
确实,似乎有。 首先请注意,您可以使用inspect
模块获取Python函数的源代码 。 然后,原则上,您可以在user_file.py
中获得setup()
函数的(新)源,并将其“发送”到main_file.py
的函数中,在该函数中可以exec
( eval
无法接受def
) -但这必须在全局上下文中完成(在main_file.py
),以便在通过exec
运行def
时替换指向旧函数的全局符号。
或例如-在OP的user_file.py
上方,只需将其添加到main之前:
# ...
import inspect
setupsrc = inspect.getsource(setup)
setsetup(setupsrc)
main()
...并添加新的功能, setsetup()
在main_file.py
:
def setsetup(instr):
#global setup # no need, globals() below takes care of it
cc=compile(instr,'abc','single')
#print(cc)
# <code object <module> at 0xb77d1218, file "abc", line 1>
print("ss1", str(setup))
exec(cc, globals()) # globals() here does the trick
print("ss2", str(setup))
然后,当我运行python user_file.py
,我得到:
...
A: setup is <function setup at 0xb774717c>
B: setup is <function setup at 0xb77476f4>
...
('ss1', '<function setup at 0xb774717c>')
('ss2', '<function setup at 0xb775a924>')
...
(' mf_glb', 'setup', 'is', <type 'function'>, 'and is equal to ', <function setup at 0xb775a924>)
...
('main_file says', 'Overloaded', 42, ' setup is <function setup at 0xb775a924>')
...表明函数已按预期重载(即使它不是正在运行的user_file.py
的setup()
实例-而是带有main_file
的源副本)。
PS:请注意,任何def
函数都还具有__code__
属性,其对象类型与compile()
的输出相同(与此相关的是在Python中,我如何获取函数中使用的全局变量? )-但是,我在这里不能真正使用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.