更多历史对话内容由豆包 AI 生成帮我写一个python技术博客 标题要吸引人 高级这里为您准备了几个不同风格的高级 Python 技术博客标题,结合您之前的 “男模系统” 项目背景,既
在 Python 的世界里,装饰器(Decorator)无疑是最具魅力的特性之一。它能在不修改原有函数代码的前提下,为函数动态添加额外功能,让代码变得更加简洁、优雅且易于维护。本文将带你从装饰器的基础概念出发,一步步深入到进阶用法,掌握这门 “魔法” 技能。
一、为什么需要装饰器?
想象一个场景:你有多个函数,需要在每个函数执行前后打印日志、计算执行时间或者进行权限验证。如果在每个函数里都重复写这些逻辑,代码会变得冗余且难以维护。装饰器正是为了解决这类问题而生 —— 它将这些通用逻辑抽取出来,通过 “装饰” 的方式动态附加到函数上。
二、装饰器的基础:函数是 “一等公民”
在 Python 中,函数是一等公民(First-Class Citizen),这意味着:
- 函数可以作为参数传递给另一个函数
- 函数可以作为返回值从另一个函数返回
- 函数可以赋值给变量
这是装饰器实现的核心基础。我们先从一个简单的例子入手:
python
运行
def greet():
print("Hello, World!")
# 将函数赋值给变量
greet_func = greet
greet_func() # 输出: Hello, World!
三、闭包:装饰器的 “前身”
闭包(Closure)是指一个函数内部定义了另一个函数,内部函数引用了外部函数的变量,并且外部函数返回了内部函数。闭包是装饰器的关键组成部分:
python
运行
def outer_function(msg):
# 外部函数变量
message = msg
def inner_function():
# 内部函数引用外部变量
print(message)
# 返回内部函数(不执行)
return inner_function
# 调用外部函数,得到内部函数的引用
my_func = outer_function("Hello, Closure!")
my_func() # 输出: Hello, Closure!
四、手写第一个装饰器
基于闭包,我们可以实现一个简单的装饰器,用于计算函数的执行时间:
python
运行
import time
def timer_decorator(func):
def wrapper():
start_time = time.time()
func() # 执行原函数
end_time = time.time()
print(f"函数执行耗时: {end_time - start_time:.4f}秒")
return wrapper
# 使用装饰器
@timer_decorator
def slow_function():
time.sleep(1)
print("函数执行完毕")
slow_function()
这里的@timer_decorator是 Python 的语法糖,等价于slow_function = timer_decorator(slow_function)。
五、进阶:装饰带参数的函数
如果原函数带有参数,我们的装饰器需要能接收并传递这些参数。可以通过*args和**kwargs来实现:
python
运行
def timer_decorator(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:.4f}秒")
return result # 返回原函数结果
return wrapper
@timer_decorator
def add(a, b):
return a + b
print(add(2, 3)) # 输出: 5 和 函数执行耗时
六、更高级:带参数的装饰器
有时候我们需要给装饰器本身传递参数,这时候需要再嵌套一层函数:
python
运行
def log_decorator(level="INFO"):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"[{level}] 函数 {func.__name__} 开始执行")
result = func(*args, **kwargs)
print(f"[{level}] 函数 {func.__name__} 执行完毕")
return result
return wrapper
return decorator
# 使用带参数的装饰器
@log_decorator(level="DEBUG")
def multiply(a, b):
return a * b
multiply(2, 3)
七、类装饰器:另一种实现方式
除了函数装饰器,Python 还支持类装饰器。类装饰器通过__call__方法实现:
python
运行
class TimerDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
start_time = time.time()
result = self.func(*args, **kwargs)
end_time = time.time()
print(f"类装饰器: 函数执行耗时 {end_time - start_time:.4f}秒")
return result
@TimerDecorator
def subtract(a, b):
return a - b
print(subtract(5, 3))
八、最佳实践:使用 functools.wraps
装饰器会 “掩盖” 原函数的元信息(如函数名、文档字符串)。使用functools.wraps可以保留原函数的元信息:
python
运行
from functools import wraps
def timer_decorator(func):
@wraps(func) # 保留原函数元信息
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"执行耗时: {end_time - start_time:.4f}秒")
return result
return wrapper
@timer_decorator
def example_function():
"""这是一个示例函数的文档字符串"""
pass
print(example_function.__name__) # 输出: example_function(而不是wrapper)
print(example_function.__doc__) # 输出: 这是一个示例函数的文档字符串
九、总结
装饰器是 Python 中强大且优雅的特性,通过它我们可以实现代码的复用和解耦。从基础的函数装饰器到进阶的带参数装饰器、类装饰器,掌握这些技巧能让你的代码更加 Pythonic。希望本文能帮助你解锁装饰器的 “魔法”,写出更优雅的代码!
更多推荐



所有评论(0)