与Global variable with imports有点相似 - 但有功能。
说我有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()
函数);但我想重载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
运行它,我会得到类似的内容:
(' 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
,但我的预期重载更改不会被打印出来。
在this中,上面链接的问题的答案中有一个教程的副本,其中解释了:
实际上,模块中的全局变量仅仅是该模块的属性(即成员实体),类似于类变量在类中的角色。当模块B由模块A导入时,B的命名空间被复制到A的。如果模块B具有全局变量X,则模块A将创建该名称的变量,其初始值是模块B在导入时对其名称的变量所具有的任何值。但是其中一个模块中对X的更改不会反映在另一个模块中。
那么,有没有办法从main_file
user_file
重载函数?事情可能会变得更加困难,因为setup()
实际上使用main_file
中的全局变量来工作......
答案 0 :(得分:0)
确实,似乎有;首先请注意,您可以使用inspect
模块get the source code of a Python function。然后,原则上,您可以在setup()
中获取user_file.py
函数的(新)来源,并将其“发送”到main_file.py
中的函数,其中它可以是{{1} }}'d(exec
无法接受eval
) - 但必须在全局上下文(此处为def
)中完成,以便指向旧函数的全局符号通过main_file.py
运行def
时会被替换。
或者作为示例 - 从OP的exec
以上,只需在main:
user_file.py
...并在# ...
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>')
正在运行的setup()
实例 - 但是它的源副本包含{{1} }。
PS:请注意,任何user_file.py
'd函数也具有main_file
属性,其对象类型与def
的输出相同(与此相关{{3但是,我不能在这里使用它。