An example of Python decorator

Summary

The decorator is essentially a Python function. It allows other functions to add additional functions without any code changes. The return value of the decorator is also a function object.

We need a decorator that can test the running time of the function, which can be defined as follows:

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print("Run time is: %s" % (end_time - start_time))
        return res
    return wrapper

Because it is a decorator, it takes a function as an argument and returns a function. We need to use Python's @ syntax , place the decorator at the definition of the function:

@timer
def fun():
    time.sleep(1)
    print("This is a test")
    return "OK"

The operation result is as follows:

This is a test
Run time is: 1.0000572204589844
OK

Put @ timer in fun () is equivalent to executing the statement:

fun = timer(fun)

If the decorator itself needs to pass in parameters, you need to write a higher-order function that returns the decorator, such as adding a name:

def timer(name):
    def decorator(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            end_time = time.time()
            print("Name is: %s ; Run time is: %s" % (name, (end_time - start_time)))
            return res
        return wrapper
    return decorator

The call and results are as follows:

@timer("Lance#")
def fun():
    time.sleep(1)
    print("This is a test")
    return "OK"
This is a test
Name is: Lance# ; Run time is: 1.0000572204589844
OK

Compared with the two-level nested decorator, the effect of three-level nesting is as follows:

fun = timer("Lance#")(fun)

Because a function is also an object, it also has properties such as name.
Before the decorator is added, the function of fun() calls the property of fun and the result is' fun '. But after decorator is added, the function's name has changed from' fun 'to' wrapper '

Therefore, you need to copy the properties of the original function, such as \.

Python's built-in functools.wraps can accomplish this task. Therefore, a complete decorator can be written as follows:

import functools

def timer(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print("Run time is: %s" % (end_time - start_time))
        return res
    return wrapper

The overall code is as follows:

__Author__ = "Lance#"

# -*- coding = utf-8 -*-

import time
import functools

def timer(name):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            end_time = time.time()
            print("Name is: %s ; Run time is: %s" % (name, (end_time - start_time)))
            return res
        return wrapper
    return decorator

@timer("Lance#")
def fun():
    time.sleep(1)
    print("This is a test")
    return "OK"

if __name__ == '__main__':
    print(fun())

Tags: Python

Posted on Mon, 04 May 2020 12:50:14 -0400 by God of Ikiliki