簡體   English   中英

覆蓋從另一個模塊導入的函數中的全局變量

[英]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

我想出了兩種可行的復雜方法,但我對其中任何一種都不滿意:

  1. 使用復制和粘貼重新定義模塊b中的x 實際功能比顯示的要復雜得多,所以這不適合我。
  2. 定義一個可以傳遞給 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM