Подтвердить что ты не робот

Как я могу заставить декоратор Python работать после завершения декорированной функции?

Я хочу использовать декоратор для обработки аудита различных функций (в основном, функции просмотра Django, но не исключительно). Для этого я хотел бы иметь возможность проверять функцию пост-исполнение - то есть функция работает как обычно, и если она возвращается без исключения, то декоратор регистрирует факт.

Что-то вроде:

@audit_action(action='did something')
def do_something(*args, **kwargs):
    if args[0] == 'foo':
        return 'bar'
    else:
        return 'baz'

Где audit_action будет работать только после завершения функции.

4b9b3361

Ответ 1

Декораторы обычно возвращают функцию-обертку; просто поместите свою логику в функцию-оболочку после вызова функции-оболочки.

def audit_action(action):
    def decorator_func(func):
        def wrapper_func(*args, **kwargs):
            # Invoke the wrapped function first
            retval = func(*args, **kwargs)
            # Now do something here with retval and/or action
            print('In wrapper_func, handling action {!r} after wrapped function returned {!r}'.format(action, retval))
            return retval
        return wrapper_func
    return decorator_func

Таким образом, audit_action(action='did something') является фабрикой декораторов, которая возвращает ограниченную область decorator_func, которая используется для украшения вашего do_something (do_something = decorator_func(do_something)).

После оформления ваша ссылка на do_something была заменена на wrapper_func. Вызов wrapper_func() вызывает исходную wrapper_func() do_something(), и тогда ваш код в функции оболочки может что-то делать.

Приведенный выше код в сочетании с вашей примерной функцией дает следующий вывод:

>>> do_something('foo')
In wrapper_func, handling action 'did something' after wrapped function returned 'bar'
'bar'

Ответ 2

Ваш декоратор может справиться с этим сам, как

def audit_action(function_to_decorate):
    def wrapper(*args, **kw):
        # Calling your function
        output = function_to_decorate(*args, **kw)
        # Below this line you can do post processing
        print "In Post Processing...."
        return output
    return wrapper