关于 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 是一个装饰器函数,它接受一个函数作为参数,并返回一个新的函数 wrapper。wrapper 函数记录了函数的执行时间,并返回函数的结果。@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还提供了更加灵活的切入点表达式,可以根据方法名、参数类型、注解等多种条件来选择切入点。

相关推荐
鶴哥只手遮天几秒前
深入理解OpenSceneGraph(五):插件生态与最佳实践
后端
伞伞悦读1 分钟前
【第53期】有序插入把二叉搜索树变成链:别只看“树”的名字
python
郝学胜_神的一滴5 分钟前
AI 编程智能体 04:一文看懂智能体的核心能力与概念辨析
人工智能·python
一缕82年的清风14 分钟前
实战指南:如何把现有 REST API 工业级封装为 MCP(Model Context Protocol)服务
python·mcp
狼与自由18 分钟前
python打包
开发语言·python
Είναι η κοπέλα24 分钟前
Python 虚拟环境:venv、conda 与 Python 版本选择全解
开发语言·python·conda
蒲公英eric24 分钟前
Python工具链与LaTeX排版:把兵器配齐
人工智能·python·算法·数学建模·数学建模工具
.道阻且长.29 分钟前
C++11 :新的类功能,lambda,包装器
开发语言·c++·后端
言乐630 分钟前
JavaScript概括前端原理
开发语言·前端·javascript·python·ecmascript
leo在掘金1 小时前
google/ax单日涨1379星:Agent编排运行时到底难在哪?
后端·架构