![](/img/trans.png)
[英]How to modify python3 globals() by key in function imported from another module?
[英]Override globals in function imported from another module
假設我有兩個模塊:
一個.py
value = 3
def x()
return value
b.py
from a import x
value = 4
我的目標是在b
中使用ax
的功能,但更改函數返回的值。 具體來說,即使在運行bx()
時,也會使用a
作為全局名稱的來源來查找value
。 我基本上是在嘗試在bx
中創建與ax
相同但使用b
獲取其全局變量的函數對象的副本。 有沒有一種相當簡單的方法來做到這一點?
這是一個例子:
import a, b
print(a.x(), b.x())
結果目前是3 3
,但我希望它是3 4
。
我想出了兩種可行的復雜方法,但我對其中任何一種都不滿意:
b
中的x
。 實際功能比顯示的要復雜得多,所以這不適合我。定義一個可以傳遞給 x 的參數,只使用模塊的值:
def x(value): return value
這給用戶增加了我想避免的負擔,並沒有真正解決問題。
有沒有辦法修改函數以某種方式獲取其全局變量的位置?
我通過猜測和檢查以及研究相結合的方式提出了一個解決方案。 您幾乎可以完全按照我在問題中提出的建議進行操作:復制一個函數對象並替換其__globals__
屬性。
我使用的是 Python 3,所以這里是對上面鏈接的問題的答案的修改版本,添加了一個選項來覆蓋全局變量:
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__)
__globals__
屬性是只讀的,這就是必須將它傳遞給 FunctionType 的構造FunctionType
的原因。 無法更改現有函數對象的__globals__
引用。
后記
我已經使用它很多次了,現在它已經在我編寫和維護的名為haggis
的實用程序庫中實現了。 請參閱haggis.objects.copy_func
。
所以我找到了一種(某種程度上)做到這一點的方法,盡管我認為它不能完全解決您的問題。 使用檢查,您可以訪問調用您的函數的文件的全局變量。 因此,如果您像這樣設置文件:
一個.py
import inspect
value = 3
def a():
return inspect.stack()[1][0].f_globals['value']
b.py
from a import a
value = 5
print(a())
輸出是 5,而不是 3。但是,如果將這兩個都導入到第三個文件中,它將查找第三個文件的全局變量。 只是想分享這個片段。
我有同樣的問題。 但后來我想起eval
是一回事。
這是一個更短的版本(如果你不需要參數):
b.py:
from a import x as xx
# Define globals for the function here
glob = {'value': 4}
def x():
return eval(xx.__code__, glob)
希望 2 年后它仍然有用
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.