python decorator, usage tutorial, execution order parsing

python decorator, usage tutorial, execution order parsing

        Decorators can usually be used to do other things, such as adding new functionality to an existing function, provided that the internal implementation of the existing function is not modified. Can be used to record function calls. Can be used to do some processing on the result. . . It can be said that the decorator is to provide a concise implementation of adding some custom functions outside the function without modifying the existing code.

    The decorator in python is relatively simple to write. Usually, a function is written, and then some functional matters are defined internally, and finally the result is returned through a unified call. This result is a unified function call interface. is usually called wrapper

A simple decorator implementation is as follows:

import functools
def trace(func):
    print "trace"

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print "trace1 before"
        result = func(*args, **kwargs)
        print "%s :%r, %r, %r" % (func.__name__, args, kwargs, result)
        print "trace1 after"
        return result

    return wrapper

@trace
def fib(n):
    if n in (0, 1):
        return n
    return fib(n - 2) + fib(n - 1)

print fib(3)

Here is the parameter situation when the function call is printed, and the result is printed out.

The implementation of a simple decorator is like this: (my understanding)

    First, build: fib = trace(fib)

    Then, execute: fib() ==> trace(fib)(*args, **kwargs) ==> wrapper(*args, **kwargs)

For multiple decorators:

import functools
def trace(func):
    print "trace"

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print "trace1 before"
        result = func(*args, **kwargs)
        # print "%s :%r, %r, %r" % (func.__name__, args, kwargs, result)
        print "trace1 after"
        return result
    return wrapper

def trace2(func):
    print "trace2"
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print "trace2 before"
        # print "%s :%r, %r, %r" % (func.__name__, args, kwargs, 0)
        result = func(*args, **kwargs)
        print "trace2 after"
        return result
    return wrapper

@trace
@trace2
def fib(n):
    if n in (0, 1):
        return n
    return fib(n - 2) + fib(n - 1)

print fib(1)

Results of the:

trace2
trace
trace1 before
trace2 before
trace2 after
trace1 after
1
The execution of multiple decorators is:
    First, build: fib = trace(trace2(fib)) # It can be understood that the parentheses are not parameters, but the order of calls
    Then, execute: fib() ==> wrapper(*args, **kwargs)
                            ==> Front operation
                            ==> wrapper2(*args, **kwargs)
                            ==> Back operation

Therefore, there is also the case of the above printout! ! !

Summary: The operation before the execution of the func in the wrapper is the same as the writing order of the decorator, and the writing order in other positions is the opposite!

It should be noted that when multiple decorators are decorated together, pay attention to the order of the decorators.
My understanding is: to distinguish the order of construction, and the order of execution.
The construction order, from the nearest one of the decorated function, builds up in order!
The execution order is divided into: the execution before the result and the execution
        after the result. The execution before the result is carried out from top to bottom according to the writing order of the decorator.

        The situation that the execution after the result is executed from bottom to top
        is caused by the operation of the stack when the method is called! be careful to use

        That's what it says in the summary! ! !

In addition: The functools.wraps decorator retains the original name of the function, some original information such as the module! ! ! In order to standardize, pay attention to add! !

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325920668&siteId=291194637