Some personal understanding of Python decorator

Decorator

  1. It is essentially a function that accepts parameters as functions.
  2. Function: add additional general functions to an implemented method, such as logging, running timing, etc.

give an example

Decorator without parameters, No@
# Decorator without parameters
def deco_test(func):
    def wrapper(*args, **kwargs):
        print("before function")
        f = func(*args, **kwargs)
        print("after function")
        return f
    return wrapper

def do_something(a,b,c):
    print(a)
    time.sleep(1)
    print(b)
    time.sleep(1)
    print(c)
    return a

if __name__ == '__main__':
    # No@
    f = deco_test(do_something)("1","2","3")

Output:

before function
1
2
3
after function

Personal understanding:

Equivalent to do_ There are two outputs outside the something function: before function and after function.

Decorator without parameters, with@
# Decorator without parameters
def deco_test(func):
    def wrapper(*args, **kwargs):
        print("before function")
        f = func(*args, **kwargs)
        print("after function")
        return f
    return wrapper

@deco_test
def do_something(a,b,c):
    print(a)
    time.sleep(1)
    print(b)
    time.sleep(1)
    print(c)
    return a

if __name__ == '__main__':
    # Use@
    f = do_something("1","2","3")

Output:

before function
1
2
3
after function

Personal understanding:

Equivalent to do_ When using something function, it is known that there is a layer of decorator Deco for @ reasons_ Test, so there is no need to write Deco separately_ Test (do_something).

Decorator with parameters
# Parameters of decorator belt
def logging(level):
    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            print("[{level}]: enter function {func}()".format(level=level, func=func.__name__))
            f = func(*args, **kwargs)
            print("after function: [{level}]: enter function {func}()".format(level=level, func=func.__name__))
            return f
        return inner_wrapper
    return wrapper

@logging(level="debug")
def do_something(a,b,c):
    print(a)
    time.sleep(1)
    print(b)
    time.sleep(1)
    print(c)
    return a

if __name__ == '__main__':
    # Use@
    f = do_something("1","2","3")

Output:

[debug]: enter function do_something()
1
2
3
after function: [debug]: enter function do_something()

Personal understanding:

The decorator takes a parameter level = "debug".

The outermost function logging() takes parameters and applies them to the inner decorator function. The inner function wrapper() takes a function as an argument and places a decorator on it. The key point here is that decorators can use the parameters passed to logging().

Class decorator
# Class decorator
class deco_cls(object):
    def __init__(self, func):
        self._func = func

    def __call__(self, *args, **kwargs):
        print("class decorator before function")
        f = self._func(*args, **kwargs)
        print("class decorator after function")
        return f

@deco_cls
def do_something(a,b,c):
    print(a)
    time.sleep(1)
    print(b)
    time.sleep(1)
    print(c)
    return a

if __name__ == '__main__':
    # Use@
    f = do_something("1","2","3")

Output:

class decorator before function
1
2
3
class decorator after function

Personal understanding:

Use a decorator to wrap the function and return a callable instance. Therefore, a class decorator is defined.

Two layer decorator
# Decorator without parameters
def deco_test(func):
    def wrapper(*args, **kwargs):
        print("before function")
        f = func(*args, **kwargs)
        print("after function")
        return f
    return wrapper

# Decorator with parameters
def logging(level):
    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            print("[{level}]: enter function {func}()".format(level=level, func=func.__name__))
            f = func(*args, **kwargs)
            print("after function: [{level}]: enter function {func}()".format(level=level, func=func.__name__))
            return f
        return inner_wrapper
    return wrapper

@logging(level="debug")
@deco_test
def do_something(a,b,c):
    print(a)
    time.sleep(1)
    print(b)
    time.sleep(1)
    print(c)
    return a

if __name__ == '__main__':
    # Use@
    f = do_something("1","2","3")

Output:

[debug]: enter function wrapper()
before function
1
2
3
after function
after function: [debug]: enter function wrapper()

Personal understanding:

In function do_something() is covered with a layer of Deco first_ Test () decorator, and then set a layer of logging() decorator on the outermost.

file

Chapter 9: meta programming

Tags: Python

Posted by computerbum on Sat, 21 May 2022 11:19:33 +0300