2016-01-20 3 views
4

Есть ли способ получить аргументы функции декоратора во время выполнения? Проект, над которым я работаю, огромен, и было бы огромным усилием переписать затронутый код. Мне нужно динамическое решение, чтобы перечислить все категории, назначенные списку функций. Для этого я хочу избежать супер хакерских решений, таких как повторное использование всех моих модулей. Можно ли это сделать, проверив кадры из стека вызовов?Получить аргументы декоратора 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