2017-08-03 127 views
2

我正在尋找一種腳本執行某些函數的方法,我不知道這些函數的名稱,並在另一個模塊(假定由另一個用戶提供)上定義,但是用我定義的模塊進行了裝飾。調用裝飾的外部函數

例如,外部腳本是:

from MyScript import preprocess, process, postprocess 

    @preprocess(foo, bar) 
    def external_provider_random_name(): 
     return "foo" 

    @process(foobar) 
    def external_provider_random(): 
     return "bar" 

    @postprocess(foo, bar) 
    def external_provider(): 
     return "foobar" 

我會在這在我的應用程序和執行功能(我不知道他們的名字),與使用什麼能力反過來又導入裝飾函數返回。

我想裝修的原因成爲燒瓶似乎暴露出類似的行爲: 用戶可以通過裝飾功能與[email protected](my/route)定義新的路線。這個函數然後在路由上執行一個http調用時執行,並且應用程序可以使用函數返回的任何內容(一個json)將其返回給用戶。

然而,似乎行爲不符合裝飾者的實際定義,我看不出我是如何實現這樣的。我在這裏錯過了什麼,或者是否只有使用裝飾器的解決方案?

+0

注意函數後面添加'函數=裝飾(功能)'就是相當於增加了'@ decorator'前它。 –

+0

這就是我可以在函數調用中添加操作的方式。但是我仍然無法確定如何調用函數,因爲我無法訪問它的名字。 – AugBar

+0

你不需要一個函數的名字來調用它。你只需要對函數的引用,這正是傳遞給你的裝飾器的東西。 – jasonharper

回答

2

您只需從包裝內鬆開傳入函數的副本即可。您可以用全局名稱,listdict或您選擇的其他方式存儲函數引用。

這裏是MyScript.py一個例子存儲其函數的引用在dict

funcs = { } 

def preprocess(*args): 
    def wrapper(fn): 
     funcs['preprocess'] = fn 
     return fn 
    return wrapper 

def process(*args): 
    def wrapper(fn): 
     funcs['process'] = fn 
     return fn 
    return wrapper 

def postprocess(*args): 
    def wrapper(fn): 
     funcs['process'] = fn 
     return fn 
    return wrapper 

所有的初始化後,可以正是如此調用功能:

MyScript.funcs['preprocess']() 
+1

在這一點上,就像在'flask'中一樣,使用一個類來封裝狀態可能是有意義的,其中裝飾器可調用實際上是一個對象的方法。 –

+0

同意。我只是選擇了一個全球的'dict'作爲一個易於理解的例子。 –

2

好像你想要創建某種功能註冊表。下面是一個簡單的示例實現,它使用字典來跟蹤註冊的函數。

class Tracker(dict): 
    def register(self, identifier): 
     def wrapper(function): 
      self[identifier] = function 
      return function 
     return wrapper 


tracker = Tracker() 

@tracker.register('A') 
def function_A(): 
    print('Blah') 

tracker['A']() # Blah 

如果你想註冊一個已定義的函數,你可以使用:

tracker.register('A')(function_A) 
+0

我非常喜歡這個想法。如果function_A的定義在腳本之外,在外部腳本之外,這將如何工作 - 我們稱之爲external.py? – AugBar

+0

@AugBar我不確定我是否知道你的意思,但我已經更新了答案,可能是爲了解決這個問題。 –

+0

該函數的定義與跟蹤器實例相同。我需要在一個單獨的文件中完成這項工作。但我認爲我有解決方案,就像完成燒瓶和藍圖一樣! – AugBar