Python 装饰器详解

装饰器是 Python 中一种强大的语法特性,它允许在不修改原函数代码的情况下动态地扩展函数的功能。装饰器本质上是一个高阶函数,它接受一个函数作为参数并返回一个新的函数。

基本装饰器

1. 简单装饰器示例

python 复制代码
def my_decorator(func):
    def wrapper():
        print("函数执行前")
        func()
        print("函数执行后")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

输出:

复制代码
函数执行前
Hello!
函数执行后

2. 装饰器的工作原理

  • @my_decorator 语法糖等价于 say_hello = my_decorator(say_hello)
  • my_decorator 接收 say_hello 函数作为参数
  • 返回 wrapper 函数,它"包裹"了原函数

带参数的装饰器

1. 函数带参数的装饰器

python 复制代码
def decorator_with_args(func):
    def wrapper(name):
        print(f"准备调用 {func.__name__}")
        func(name)
        print(f"{func.__name__} 调用完成")
    return wrapper

@decorator_with_args
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

2. 装饰器本身带参数

python 复制代码
def repeat(num_times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                func(*args, **kwargs)
        return wrapper
    return decorator

@repeat(3)
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Bob")

输出:

复制代码
Hello, Bob!
Hello, Bob!
Hello, Bob!

类装饰器

装饰器不仅可以是函数,还可以是类:

python 复制代码
class CountCalls:
    def __init__(self, func):
        self.func = func
        self.num_calls = 0

    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        print(f"函数已被调用 {self.num_calls} 次")
        return self.func(*args, **kwargs)

@CountCalls
def example():
    print("执行示例函数")

example()
example()
example()

输出:

复制代码
函数已被调用 1 次
执行示例函数
函数已被调用 2 次
执行示例函数
函数已被调用 3 次
执行示例函数

多个装饰器叠加

可以同时应用多个装饰器:

python 复制代码
def uppercase_decorator(func):
    def wrapper():
        result = func()
        return result.upper()
    return wrapper

def exclamation_decorator(func):
    def wrapper():
        result = func()
        return result + "!"
    return wrapper

@exclamation_decorator
@uppercase_decorator
def say_hi():
    return "hi there"

print(say_hi())  # 输出: HI THERE!

注意:装饰器的应用顺序是从下往上,先应用 uppercase_decorator,然后是 exclamation_decorator

内置装饰器

Python 本身提供了一些内置装饰器:

  1. @staticmethod - 定义静态方法
  2. @classmethod - 定义类方法
  3. @property - 将方法转换为属性

装饰器的常见用途

  1. 日志记录
  2. 性能测试(计算函数执行时间)
  3. 权限验证
  4. 缓存(备忘录模式)
  5. 输入验证
  6. 注册插件
  7. 重试机制

性能测试装饰器示例

python 复制代码
import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} 执行时间: {end - start:.4f} 秒")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(2)

slow_function()

保留原函数的元信息

使用 functools.wraps 可以保留原函数的元信息:

python 复制代码
from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """这是包装函数的文档字符串"""
        print("装饰器添加的功能")
        return func(*args, **kwargs)
    return wrapper

@my_decorator
def example():
    """这是原函数的文档字符串"""
    print("原函数功能")

print(example.__name__)  # 输出: example
print(example.__doc__)   # 输出: 这是原函数的文档字符串

总结

装饰器是 Python 中非常强大的特性,它:

  • 允许在不修改原函数代码的情况下扩展功能
  • 遵循开放-封闭原则(对扩展开放,对修改封闭)
  • 使代码更加模块化和可重用
  • 常用于日志、性能测试、权限控制等场景

掌握装饰器可以让你写出更加优雅和高效的 Python 代码。

相关推荐
老前端的功夫2 分钟前
【Java从入门到入土】28:Stream API:告别for循环的新时代
java·开发语言·python
qq_435287923 分钟前
第9章 夸父逐日与后羿射日:死循环与进程终止?十个太阳同时值班的并行冲突
java·开发语言·git·死循环·进程终止·并行冲突·夸父逐日
止语Lab15 分钟前
从手动到框架:Go DI 演进的三个拐点
开发语言·后端·golang
yaoxin52112329 分钟前
397. Java 文件操作基础 - 创建常规文件与临时文件
java·开发语言·python
小短腿的代码世界33 分钟前
Qt日志系统深度解析:从qDebug到企业级日志框架
开发语言·qt
dFObBIMmai39 分钟前
MySQL主从同步中大事务导致的延迟_如何拆分大事务优化同步
jvm·数据库·python
szccyw042 分钟前
mysql如何限制特定存储过程执行权限_MySQL存储过程安全访问
jvm·数据库·python
小白学大数据1 小时前
Python 自动化爬取网易云音乐歌手歌词实战教程
爬虫·python·okhttp·自动化
REDcker1 小时前
浏览器端Web程序性能分析与优化实战 DevTools指标与工程清单
开发语言·前端·javascript·vue·ecmascript·php·js
风之所往_2 小时前
Python 3.0 新特性全面总结
python