欢迎访问宙启技术站
智能推送

Python装饰器的使用方法和示例:为函数增加额外功能

发布时间:2023-06-10 05:02:48

Python装饰器是一种处理函数的高级方法,它允许在不改变函数代码的情况下为函数添加额外的功能。在实际开发中,我们经常需要为函数添加类似于日志记录、性能统计、缓存等功能,使用装饰器可以使这些功能与原始函数解耦,并且可以重用装饰器,使代码更加简洁。本文将介绍Python装饰器的使用方法和示例。

一、装饰器的基本用法

装饰器是一个函数,它接受一个函数作为参数,并返回新的函数。新函数可以调用原始函数,并添加额外的操作。以下是一个简单的装饰器示例:

def my_decorator(func):
    def wrapper():
        print("wrapper start...")
        func()
        print("wrapper end...")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

输出结果:

wrapper start...
Hello!
wrapper end...

在这个示例中,我们定义了一个名为my_decorator的装饰器函数,它接受一个函数作为参数。wrapper函数调用了原始函数func,并添加了额外的操作。在say_hello函数前面加上了@my_decorator,相当于将say_hello函数作为参数传递给my_decorator函数,并将返回的新函数赋值给say_hello变量。

二、装饰器的进阶用法

除了在函数前面使用@decorator语法糖,装饰器还可以在函数内部手动调用。这种用法和函数嵌套很像,可以增加装饰器的灵活性和可重用性。以下是一个示例:

def my_decorator(func):
    def wrapper():
        print("wrapper start...")
        func()
        print("wrapper end...")
    return wrapper

def say_hello():
    print("Hello!")

decorated_say_hello = my_decorator(say_hello)
decorated_say_hello()

输出结果和前面的示例一样:

wrapper start...
Hello!
wrapper end...

在这个示例中,我们手动调用了my_decorator函数,并将原始函数say_hello作为参数传递进去,最后将返回的新函数赋值给decorated_say_hello变量,然后调用这个新函数。

装饰器还可以接收参数,并传递给原始函数。以下是一个示例:

def repeat(num):
    def my_decorator(func):
        def wrapper():
            for i in range(num):
                func()
        return wrapper
    return my_decorator

@repeat(num=3)
def say_hello():
    print("Hello!")

say_hello()

输出结果:

Hello!
Hello!
Hello!

在这个示例中,我们定义了一个名为repeat的装饰器,它接收一个参数num,表示重复调用原始函数多少次。my_decorator函数再次定义了一个wrapper函数,用于循环调用原始函数。在say_hello函数前面使用了@repeat(num=3),相当于将num=3作为参数传递给了repeat装饰器。

三、常见的装饰器应用

1. 记录日志

在实际开发中,我们常常需要记录函数的调用过程,以便后续的分析和排查。使用装饰器可以很方便地实现这个功能:

def log_execution(func):
    def wrapper(*args, **kwargs):
        print(f"{func.__name__} start...")
        result = func(*args, **kwargs)
        print(f"{func.__name__} end...")
        return result
    return wrapper

@log_execution
def say_hello():
    print("Hello!")

say_hello()

输出结果:

say_hello start...
Hello!
say_hello end...

在这个示例中,我们定义了一个名为log_execution的装饰器函数,它接收一个函数作为参数。wrapper函数记录了原始函数的开始和结束时间,并在调用后返回原始函数的结果。在say_hello函数前面使用了@log_execution,相当于将say_hello函数作为参数传递给了log_execution装饰器。

2. 统计函数执行时间

除了记录函数的调用过程,我们还经常需要统计函数的执行时间。使用装饰器可以很方便地实现这个功能:

import time

def measure_time(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} took {end - start:.3f}s")
        return result
    return wrapper

@measure_time
def count_sum(n):
    return sum(range(n))

print(count_sum(1000000))

输出结果:

499999500000
count_sum took 0.031s

在这个示例中,我们定义了一个名为measure_time的装饰器函数,它接收一个函数作为参数。wrapper函数记录了原始函数的开始和结束时间,并在调用后输出函数的执行时间。在count_sum函数前面使用了@measure_time,相当于将count_sum函数作为参数传递给了measure_time装饰器。

3. 缓存函数

在一些计算密集型的函数中,我们可能会需要缓存计算结果,以避免重复计算浪费时间。使用装饰器可以很方便地实现这个功能:

def memoize(func):
    cache = {}

    def wrapper(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]

    return wrapper

@memoize
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(30))

输出结果:

832040

在这个示例中,我们定义了一个名为memoize的装饰器函数,它接收一个函数作为参数。wrapper函数记录了原始函数的参数和返回值,以避免重复计算。在fib函数前面使用了@memoize,相当于将fib函数作为参数传递给了memoize装饰器。

四、总结

Python装饰器是一种处理函数的高级方法,它允许在不改变函数代码的情况下为函数添加额外的功能。在实际开发中,我们经常需要为函数添加类似于日志记录、性能统计、缓存等功能,使用装饰器可以使这些功能与原始函数解耦,并且可以重用装饰器,使代码更加简洁。本文介绍了装饰器的基本用法和进阶用法,并举了一些常见的装饰器应用示例。在使用装饰器时,需要理解装饰器函数的参数、返回值和作用范围,并了解装饰器的调用顺序和优先级。