关于 python 装饰器,你了解多少?

一、装饰器介绍

装饰器是 Python 中的一种语法,它可以在不改变源代码的前提下,修改或增强函数或类的功能。装饰器本质上是一个函数或类,它接受一个函数或类作为参数,并返回一个新的函数或类。在 Python 中,装饰器通常使用 @ 符号来应用。

装饰器可以用于很多场景,例如:

  • 记录函数执行时间
  • 缓存函数的返回值
  • 检查函数参数的类型和取值范围
  • 给函数添加日志记录
  • 给函数添加权限验证
  • 给函数添加重试机制
  • 等等

二、装饰器使用

2.1 函数的装饰器

下是一个简单的装饰器示例,它可以用来记录函数的执行时间:

python 复制代码
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__} took {end_time - start_time:.2f} seconds to run.")
        return result
    return wrapper

@timer
def my_function():
    time.sleep(1)

my_function()

输出

text 复制代码
my_function took 1.00 seconds to run.

在上面的代码中,timer 是一个装饰器函数,它接受一个函数作为参数,并返回一个新的函数 wrapperwrapper 函数记录了函数的执行时间,并返回函数的结果。@timer 表示将 my_function 函数应用 timer 装饰器,从而在调用 my_function 函数时自动记录函数的执行时间。

2.2类的装饰器

类装饰器通过将装饰器逻辑封装到一个类中,使得装饰器更加灵活和可复用。 要创建一个类装饰器,我们需要定义一个类,并实现以下两个方法之一:__init____call__

  • __init__方法会在装饰器创建时调用,可以用来初始化装饰器的参数。
  • __call__方法会在装饰器应用于被装饰的函数时被调用,可以用来包装并修改函数的行为
python 复制代码
class Logger:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print(f"Logging: Calling function {self.func.__name__}")
        return self.func(*args, **kwargs)

@Logger
def say_hello():
    print("Hello, world!")

say_hello()

输出

text 复制代码
Logging: Calling function say_hello
Hello, world!

特别是如果有多个函数或者多个类需要计算执行时间的话,这种方式避免大量代码的冗余


三、 扩展:Python的装饰器和Java Spring的面向切面编程 区别

用过 Spring 的同学,应该会好奇这个问题。

Python的装饰器是一种语法糖,它允许在不修改被装饰函数源代码的情况下,通过在函数定义前添加一个装饰器函数来修改函数的行为。装饰器函数接受被装饰函数作为参数,并返回一个新的函数对象,该函数对象可以替代原始函数。装饰器可以用于实现缓存、日志记录、性能分析等功能。

Java Spring的AOP是一种编程范式,它允许在不修改原始代码的情况下,通过在运行时动态地将代码切入到方法调用中来实现横切关注点的功能。AOP通过将横切关注点(如日志记录、事务管理、安全性检查等)从业务逻辑中分离出来,使得代码更加模块化和可维护。

虽然Python的装饰器和Java Spring的AOP都可以用于实现横切关注点的功能,但它们的实现方式有所不同。Python的装饰器是一种语法糖,它只能修改函数的行为,而Java Spring的AOP是一种更加通用的编程范式,它可以用于修改任何对象的行为。此外,Java Spring的AOP还提供了更加灵活的切入点表达式,可以根据方法名、参数类型、注解等多种条件来选择切入点。

相关推荐
pzx_0015 分钟前
【内积】内积计算公式及物理意义
数据结构·python·opencv·算法·线性回归
一丝晨光6 分钟前
逻辑运算符
java·c++·python·kotlin·c#·c·逻辑运算符
ForRunner1239 分钟前
使用 Python 高分解决 reCAPTCHA v3 的指南
数据库·python·microsoft
无名指的等待71230 分钟前
SpringBoot中使用ElasticSearch
java·spring boot·后端
.生产的驴1 小时前
SpringBoot 消息队列RabbitMQ 消费者确认机制 失败重试机制
java·spring boot·分布式·后端·rabbitmq·java-rabbitmq
躺平的花卷1 小时前
Python爬虫案例六:抓取某个地区某月份天气数据并保存到mysql数据库中
数据库·爬虫·python·mysql
虚拟搬运工1 小时前
Python类及元类的创建流程
开发语言·chrome·python
学步_技术2 小时前
Python编码系列—Python原型模式:深克隆与高效复制的艺术
开发语言·python·原型模式
Desire.9842 小时前
Python 数学建模——灰色关联度分析
python·数学建模·灰色关联度
苹果酱05672 小时前
一文读懂SpringCLoud
java·开发语言·spring boot·后端·中间件