前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python懒人必备:推荐7个高效实用的装饰器!

Python懒人必备:推荐7个高效实用的装饰器!

作者头像
测试开发技术
发布2024-09-10 21:17:31
1940
发布2024-09-10 21:17:31
举报
文章被收录于专栏:测试开发技术

对于编程新手来说,Python装饰器可能是一个稍显复杂的概念。简单来说,装饰器是一个函数,它可以接受另一个函数作为参数,并返回一个新的函数(通常是修改后的原始函数的版本)。这个特性使得装饰器在Python中成为一种非常强大且灵活的工具,可以用于在不修改原始函数代码的情况下,为其添加新的功能或修改其行为。常用于统计时间、插入日志、性能度量、权限校验、缓存、事务处理等场景。

想象一下,你有一个函数,它负责计算两个数的和。现在,你希望为这个函数添加一个计时功能,以便知道它执行需要多长时间。使用装饰器,你可以在不修改原始函数的情况下实现这一点。你只需编写一个装饰器函数,它接受原始函数作为参数,并返回一个新的函数,这个新函数在调用原始函数之前和之后分别记录时间,并计算执行时间。然后,你可以将这个装饰器应用到你的原始函数上,从而得到一个具有计时功能的新函数。

下述,列举几个常见装饰器的用法及示例,希望对大家有些许帮助。

1、计时装饰器

计时装饰器在Python中主要用于测量函数的执行时间,这在性能调优和代码优化时非常有用。例如,当你有一个复杂的算法或函数,你想知道它需要多长时间才能完成,或者你想比较两个不同实现的性能差异,你可以使用计时装饰器来测量它们的运行时间。

代码语言:javascript
复制
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 test_function():
    time.sleep(3)
    print("示例函数执行完毕")

test_function()

2、日志装饰器

日志装饰器的主要用途是在不修改原函数代码的情况下,为函数增加日志记录的功能。这样可以帮助开发者更好地了解程序的运行状态,跟踪错误以及分析性能问题。

代码语言:javascript
复制
import logging

def log_decorator(func):
    def wrapper(*args, **kwargs):
        logging.basicConfig(level=logging.INFO)
        logging.info(f"开始执行 {func.__name__} 函数")
        result = func(*args, **kwargs)
        logging.info(f"{func.__name__} 函数执行完毕")
        return result
    return wrapper

@log_decorator
def example_function():
    print("示例函数执行中...")

example_function()

3、缓存装饰器

缓存装饰器主要用于优化程序的性能,特别是在处理重复计算或I/O操作时。

代码语言:javascript
复制
import functools

def cache_decorator(func):
    cache = dict()

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        key = (args, tuple(kwargs.items()))
        if key not in cache:
            cache[key] = func(*args, **kwargs)
        return cache[key]

    return wrapper

@cache_decorator
def example_function(x, y):
    return x + y

print(example_function(1, 2))  # 输出 3,计算并缓存结果
print(example_function(1, 2))  # 输出 3,从缓存中获取结果

也可以使用functools.lru_cache来实现缓存装饰器的效果

代码语言:javascript
复制
import functools

@functools.lru_cache(maxsize=None)
def example_function(x, y):
    return x + y

print(example_function(1, 2))  # 输出 3,计算并缓存结果
print(example_function(1, 2))  # 输出 3,从缓存中获取结果

functools.lru_cache使用最近最少使用(LRU)策略来管理缓存的大小,这意味着它会保留最近使用的函数调用结果,而将长时间未使用的结果清除以释放内存空间。此外,lru_cache还提供了一些高级参数,如最大缓存大小、缓存过期时间等,使得开发者可以根据需求对缓存行为进行更细致的控制。

4、类型检查装饰器

类型检查装饰器在Python中主要用于确保函数调用时参数的数据类型与预期匹配,从而提高代码的健壮性和可维护性。

代码语言:javascript
复制
from functools import wraps

def type_check(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        # 获取函数的参数注解
        annotations = func.__annotations__
        
        # 遍历参数和注解,检查类型是否正确
        for arg, annotation in zip(args, annotations.values()):
            if not isinstance(arg, annotation):
                raise TypeError(f"参数 {arg} 的类型应为 {annotation},但实际类型为 {type(arg)}")
        
        # 调用原始函数
        return func(*args, **kwargs)
    
    return wrapper

# 使用装饰器进行类型检查
@type_check
def add(a: int, b: int) -> int:
    return a + b

print(add(1, 2))  # 输出 3
print(add("1", "2"))  # 抛出 TypeError,因为参数类型不正确

5、单例装饰器

单例模式是一种设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。在Python中,可以使用装饰器来实现单例模式。以下是一个简单的单例装饰器示例:

代码语言:javascript
复制
def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance

@singleton
class MyClass:
    def __init__(self, x):
        self.x = x

a = MyClass(1)
b = MyClass(2)
print(a is b)  # 输出 True,说明 a 和 b 是同一个实例

6、重试装饰器

重试装饰器主要用于实现自动重试逻辑,以提高系统的稳定性和可靠性。以下是一个简单的重试装饰器示例:

代码语言:javascript
复制
import time
from functools import wraps

def retry(retries=3, delay=1):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for i in range(retries):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if i == retries - 1:
                        raise e
                    time.sleep(delay)
        return wrapper
    return decorator

@retry(retries=5, delay=2)
def my_function():
    # 这里是你的函数实现
    pass

在这个示例中,retry 装饰器接受两个参数:retries 表示最大重试次数,默认为3次;delay 表示每次重试之间的延迟时间,默认为1秒。当被装饰的函数抛出异常时,装饰器会自动重试指定次数,并在每次重试之间等待指定的延迟时间。如果达到最大重试次数仍然失败,则抛出最后一次捕获到的异常。

7、性能度量装饰器

cProfile是Python内置的性能分析工具,可以用于测量函数的执行时间和调用次数等信息。以下是使用cProfile来实现性能度量装饰器的示例:

代码语言:javascript
复制
import cProfile
from functools import wraps

def performance_metric(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        profiler = cProfile.Profile()
        profiler.enable()
        result = func(*args, **kwargs)
        profiler.disable()
        profiler.print_stats()
        return result
    return wrapper

@performance_metric
def my_function():
    # 这里是你的函数实现
    pass

在这个示例中,我们首先导入了cProfile模块,并定义了一个名为performance_metric的装饰器。在装饰器内部,我们创建了一个cProfile.Profile对象,并启用它来开始性能分析。然后,我们调用原始函数并获取结果。最后,我们禁用性能分析器并打印出性能分析结果。

使用这个装饰器非常简单,只需要在需要测量性能的函数上方添加 @performance_metric 即可。例如,在上面的示例中,我们在 my_function 函数上使用了该装饰器,因此每次调用 my_function 时都会自动输出其性能分析结果。

如果觉得有用,就请关注、点赞、在看、分享到朋友圈吧!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 测试开发技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档