Principle and Usage Summary of python decorator

principle

The decorator is also a function in nature, but this function needs to follow the following rules:

  • There can only be one input parameter of type function. The decorated function will be passed in this parameter
  • The return value must be a function. When it is called, it actually calls the returned function, so the return function input parameter is usually
(*args, **kwargs):

To satisfy all functions

After that, you can decorate any function with @ syntax sugar

Simple decorator example

# Decorator without parameters
def pre_do_sth(func):
    def wrapper(*args, **kwargs):
        print("Do sth before call one")
        func(*args, **kwargs)
    return wrapper
  
@pre_do_sth
def echo(msg):
    print(msg)
    
echo("Hello World")

Operation results

Do sth before call one
Hello World

In fact, the wrapper ("Hello world") -- > echo ("Hello world") is called

Examples of decorators with parameters (parameters control the behavior of decorators)

You only need to write a function that returns a decorator (only one input parameter, and the return value is a function)

You can also use @ grammar sugar

# Decorator with parameters
def pre_do_sth_2(msg):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print("Do sth before call two, print:%s"%(msg))
            func(*args, **kwargs)
        return wrapper
    return decorator


@pre_do_sth_2("Foo")
def echo(msg):
    print(msg)

echo("Hello World")

In fact, @ does not take effect on the function pre do sth 2, but on the return value of pre do sth 2

Operation results

Do sth before call two, print:Foo
Hello World

Multiple decorator call order

The first declared decorator executes first, that is, at the outermost layer

# Decorator without parameters
def pre_do_sth(func):
    def wrapper(*args, **kwargs):
        print("Do sth before call one")
        func(*args, **kwargs)
    return wrapper

# Decorator with parameters
def pre_do_sth_2(msg):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print("Do sth before call two, print:%s"%(msg))
            func(*args, **kwargs)
        return wrapper
    return decorator


@pre_do_sth
@pre_do_sth_2("Foo")
def echo(msg):
    print(msg)

echo("Hello World")

Operation results

Do sth before call one
Do sth before call two, print:Foo
Hello World

Tags: Python

Posted on Mon, 04 May 2020 17:56:00 -0400 by departedmind