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

Python装饰器的作用和优势是什么

发布时间:2023-12-15 19:56:59

Python的装饰器(decorator)是一种高级技术,它可以修改或增强一个函数的功能而不需要改变函数的定义。装饰器本质上是一个函数,它接受一个被装饰的函数作为参数,并返回一个新的函数。

装饰器的作用和优势:

1. 代码复用:装饰器能够将一些常用的功能代码封装成一个装饰器函数,使得这些功能可以被不同的函数共享,从而减少了代码的重复编写。

2. 扩展功能:通过装饰器,我们可以在不改变原函数的代码的情况下,给函数添加一些新的功能,比如执行前后的日志记录、性能测试、异常处理等。

3. 动态修改函数:装饰器可以在函数运行时对函数的行为进行动态修改,这种能力可以用来实现一些特殊的功能,比如缓存、断路器、权限验证等。

下面是一些常见的装饰器的使用例子:

1. 记录函数执行时间的装饰器

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"函数 {func.__name__} 的执行时间为 {end_time-start_time} 秒")
        return result
    return wrapper

@timer
def my_function():
    time.sleep(2)
    print("Hello, world!")

my_function()
# 输出:函数 my_function 的执行时间为 2.000209093093872 秒

上面的装饰器@timer会在执行被装饰的函数my_function之前和之后记录时间并输出。

2. 记录函数调用日志的装饰器

def logger(func):
    def wrapper(*args, **kwargs):
        print(f"调用了函数 {func.__name__},参数为 {args}, {kwargs}")
        result = func(*args, **kwargs)
        print(f"函数 {func.__name__} 的返回值为 {result}")
        return result
    return wrapper

@logger
def add(a, b):
    return a + b

add(3, 4)
# 输出:调用了函数 add,参数为 (3, 4), {}
#     函数 add 的返回值为 7

上面的装饰器@logger会在调用被装饰的函数add之前和之后记录日志并输出。

3. 权限验证的装饰器

def require_login(func):
    def wrapper(*args, **kwargs):
        if is_logged_in():
            return func(*args, **kwargs)
        else:
            raise Exception("请登录后操作")
    return wrapper

@require_login
def delete_item(item_id):
    print(f"删除了 ID 为 {item_id} 的物品")

delete_item(123)
# 输出:请登录后操作

上面的装饰器@require_login会在调用被装饰的函数delete_item之前检查当前用户是否已登录,如果未登录则抛出异常。

4. 缓存函数结果的装饰器

def cache(func):
    cached_results = {}

    def wrapper(*args, **kwargs):
        key = (args, frozenset(kwargs.items()))
        if key in cached_results:
            return cached_results[key]
        else:
            result = func(*args, **kwargs)
            cached_results[key] = result
            return result

    return wrapper

@cache
def factorial(n):
    if n == 0 or n == 1:
        return 1
    else:
        return n * factorial(n-1)

factorial(5)
# 输出:120

上面的装饰器@cache会缓存函数factorial的结果,避免重复计算。

这些例子展示了装饰器的一些应用场景,但装饰器的使用场景远不止于此。通过编写自定义的装饰器函数,我们可以灵活地扩展和修改函数的行为,从而使我们的代码更具可读性和可维护性。