2013-12-14 138 views
1

有點類似於Global variable with imports - 但帶有函數。重載在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()函數);但我想超載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

你真的不應該這樣做與全局變量。我建議找到另一種方式來傳遞狀態信息。也許定義一個類。 – user2357112

+0

感謝評論@ user2357112!我應該提到,我知道類在這種情況下是正確的,但我對原理上的工作原理感興趣(還有,我有一個「main_file」,爲此port它到一個類可能不值得':)')乾杯! – sdaau

回答

0

確實,似乎有;首先請注意,您可以使用inspect模塊get the source code of a Python function。然後,原則上,您可以在user_file.py中獲得setup()函數的(新)來源,並將其「發送」到main_file.py中的函數,它可以是exec'd(eval不能接受def) - 但必須完成在全局範圍內(這裏是main_file.py),以便在通過exec運行def時替換指向舊功能的全局符號。

還是爲例 - 以上user_file.py從OP,之前主要補充一點:

# ... 

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()在其內部運行user_file.py實例 - 但withing main_file它的源副本

PS:注意,任何def「d功能也有__code__屬性,與compile()(與此相關的是In Python, how can I get the global variables that are used in a function?)的輸出具有相同類型的對象 - 但是,在這裏我無法真正使用它。