2016-01-20 110 views
4

是否有任何一種方式在運行時獲取裝飾器函數的參數?我正在進行的項目非常龐大,重寫受影響的代碼將是一項巨大的工作。我需要一個動態解決方案來列出分配給功能列表的所有「類別」。爲此,我想避免超級黑客解決方案,比如通過我的所有模塊進行regexing。這可以通過檢查調用堆棧中的幀來完成嗎?在運行時獲取python裝飾器參數

在我們的環境中,函數是對象方法,我們也使用鏈接裝飾器。爲了便於理解,我將這些代碼放在一起。

如果這是不可能的,我可以爲項目的某些部分組合另一個裝飾器,但它會增加更多的複雜性。但是任何解決我的問題的建議都是值得歡迎的。

def check(*args): 
    # do something project relevant, so just return True 
    return True 

def decorate(*categories): 
    def wrap(f): 
     def wrap_check_categories(*args, **kwargs): 
      if check(*categories): 
       return f(*args, **kwargs) 
      else: 
       raise Exception 
     return wrap_check_categories 
    return wrap 

def get_categories(f): 
    '''Returns decorator parameters''' 
    # ... do some magic here 
    raise NotImplementedError 

@decorate('foo', 'bar') 
def fancy_func(*args, **kwargs): 
    return args, kwargs 

def main(): 
    ## should output ['foo', 'bar'] 
    print get_categories(fancy_func) 

if __name__ == '__main__': 
    main() 

回答

2

修改裝飾存儲類別下的裝飾功能的一個屬性(例如_args):

def check(*args): 
    # do something project relevant, so just return True 
    return True 

def decorate(*categories): 
    def wrap(f): 
     def wrap_check_categories(*args, **kwargs): 
      if check(*categories): 
       return f(*args, **kwargs) 
      else: 
       raise Exception 
     wrap_check_categories._args = categories # <-- store the categories 
     return wrap_check_categories 
    return wrap 

def get_categories(f): 
    '''Returns decorator parameters''' 
    # ... do some magic here 
    return f._args 

@decorate('foo', 'bar') 
def fancy_func(*args, **kwargs): 
    return args, kwargs 

def main(): 
    ## should output ['foo', 'bar'] 
    print get_categories(fancy_func) 

if __name__ == '__main__': 
    main() 

產量

('foo', 'bar') 
+0

真棒!謝謝! – atomocopter