百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Python装饰器常用使用场景举例(python应用场景)

toyiye 2024-06-30 09:41 21 浏览 0 评论

Python装饰器是一种强大的工具,用于在不修改原有函数代码的基础上为其添加额外的功能。以下是一些具体使用装饰器的示例:

示例1:日志记录

装饰器可以用来为函数添加日志记录功能,以便追踪函数的调用情况。

import logging

def log_decorator(func):
    def wrapper(*args, **kwargs):
        logging.info(f"Calling function {func.__name__} with args={args}, kwargs={kwargs}")
        result = func(*args, **kwargs)
        logging.info(f"Function {func.__name__} returned: {result}")
        return result
    return wrapper

@log_decorator
def calculate_sum(a, b):
    return a + b

calculate_sum(3, 5)  # 输出类似:Calling function calculate_sum with args=(3, 5), kwargs={}
                     #           Function calculate_sum returned: 8

在这个例子中,log_decorator 装饰器会在调用 calculate_sum 函数前后分别记录一条日志,显示函数名、传入的参数和返回的结果。

示例2:性能计时

装饰器可以用来测量函数的执行时间,有助于性能分析和优化。

import time

def timer_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        execution_time = end_time - start_time
        print(f"Function {func.__name__} executed in {execution_time:.6f} seconds")
        return result
    return wrapper

@timer_decorator
def process_data(data):
    # 复杂的数据处理逻辑
    pass

process_data(some_large_dataset)  # 输出类似:Function process_data executed in 1.234567 seconds

timer_decorator 装饰器在调用 process_data 函数前后记录开始和结束时间,计算并打印出函数的执行时间。

示例3:权限检查

装饰器可以用于实现函数级别的权限检查,确保只有授权用户才能执行某些操作。

def login_required(func):
    def wrapper(user, *args, **kwargs):
        if not user.is_authenticated:
            raise AuthenticationError("User must be logged in to perform this action.")
        return func(user, *args, **kwargs)
    return wrapper

class User:
    def __init__(self, is_authenticated=False):
        self.is_authenticated = is_authenticated

@login_required
def edit_profile(user):
    # 编辑用户个人资料的逻辑
    pass

user = User(is_authenticated=True)
edit_profile(user)  # 正常执行
user = User(is_authenticated=False)
edit_profile(user)  # 抛出 AuthenticationError

login_required 装饰器检查传入的 user 是否已登录,若未登录则抛出异常。这样,只需在需要权限控制的函数上使用该装饰器,即可实现一致的权限检查逻辑。

示例4:缓存结果

装饰器可以用于缓存函数的返回结果,避免重复计算,提高性能。

from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(30))  # 第一次调用会计算结果,后续调用相同参数时直接返回缓存结果

在这个例子中,使用了Python标准库中的 functools.lru_cache 装饰器,它会缓存最近计算过的 fibonacci 函数的结果,当再次以相同参数调用时,直接返回缓存的值,而不是重新计算。

以上四个示例演示了Python装饰器在日志记录、性能计时、权限检查和结果缓存等场景中的应用,体现了装饰器在简化代码、增强功能和提高性能方面的价值。


下面介绍一下Python装饰器常用的使用技巧:

1. 带有参数的装饰器

装饰器通常不直接接收参数,但如果需要为装饰器提供额外配置,可以创建一个返回装饰器的工厂函数:

from functools import wraps

def cache(ttl=60):
    """带有缓存过期时间参数的装饰器"""
    def decorator(func):
        @wraps(func)  # 保持被装饰函数的元信息
        def wrapper(*args, **kwargs):
            # 这里省略具体的缓存逻辑,如使用键值对存储结果
            result = get_from_cache(args, kwargs) or calculate_result(func, *args, **kwargs)
            set_to_cache(args, kwargs, result, ttl=ttl)
            return result
        return wrapper
    return decorator

@cache(ttl=30)
def expensive_computation(a, b):
    """耗时的计算函数"""
    # 实现复杂的计算逻辑
    pass

在这个例子中,cache 函数接收一个 ttl 参数(缓存过期时间),返回一个真正的装饰器 decorator。这样,我们就可以根据需要为不同的函数指定不同的缓存过期时间。

2. 多个装饰器的组合(复合装饰器)

一个函数可以被多个装饰器依次包装,形成装饰器链。这种组合方式使得不同功能的装饰器可以叠加应用于同一个函数:

def log_call(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__} with args={args}, kwargs={kwargs}")
        result = func(*args, **kwargs)
        print(f"{func.__name__} returned: {result}")
        return result
    return wrapper

def authenticate(user_level='basic'):
    def decorator(func):
        def wrapper(*args, **kwargs):
            check_user_auth(user_level)
            return func(*args, **kwargs)
        return wrapper
    return decorator

@authenticate(user_level='admin')
@log_call
def update_database(data):
    """更新数据库操作"""
    # 实现数据库更新逻辑
    pass

此处,update_database 函数先经过 authenticate 装饰器进行用户身份验证,然后再由 log_call 装饰器记录函数调用情况。装饰器的执行顺序遵循从上到下的应用顺序。

3. 类装饰器

类也可以作为装饰器使用,尤其适用于需要保存状态或执行更复杂逻辑的情况:

class RateLimiter:
    def __init__(self, max_calls_per_minute=60):
        self.calls_made = 0
        self.max_calls_per_minute = max_calls_per_minute
        self.reset_time = time.time() + 60

    def __call__(self, func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if self.calls_made < self.max_calls_per_minute:
                self.calls_made += 1
                return func(*args, **kwargs)
            elif time.time() >= self.reset_time:
                self.calls_made = 1
                self.reset_time = time.time() + 60
                return func(*args, **kwargs)
            else:
                raise RateLimitExceeded("Rate limit exceeded.")
        return wrapper

@RateLimiter(max_calls_per_minute=30)
def send_email(to, subject, body):
    """发送电子邮件函数"""
    # 实现邮件发送逻辑
    pass

RateLimiter 类作为一个装饰器,限制了 send_email 函数每分钟的最大调用次数。类装饰器的优势在于可以利用类的特性(如类变量和方法)来保存和管理状态。

4. 使用第三方库提供的装饰器

许多Python库(如Flask、Django、pytest等)提供了现成的装饰器,简化常见任务的实现。例如,Flask中的路由装饰器:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/api/users', methods=['GET'])
def list_users():
    """定义一个处理GET请求的路由"""
    users = fetch_users_from_database()
    return jsonify(users)

这里,@app.route 是Flask提供的装饰器,它将 list_users 函数与指定的URL路径和HTTP方法关联起来,无需手动处理HTTP请求和响应。

以上就是Python装饰器的一些使用技巧示例,包括带有参数的装饰器、复合装饰器、类装饰器以及使用第三方库提供的装饰器,它们展示了装饰器在实际编程中如何帮助我们简洁、高效地实现多种功能。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码