重载在Python中使用全局变量的导入函数

时间:2013-12-14 02:11:42

标签: python overloading

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中的全局变量来工作......

1 个答案:

答案 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但是,我不能在这里使用它。