python装饰器是一种接收函数并返回增强函数的高阶函数,用于在不修改原始函数代码的前提下增加功能。1. 装饰器通过闭包和函数作为一等公民的特性,实现对原函数的包裹和行为增强;2. 使用@语法糖简化装饰器应用,等价于函数赋值操作;3. 为保留被装饰函数的元数据,应使用functools.wraps;4. 多重装饰器按从下往上的顺序执行;5. 带参数的装饰器需通过装饰器工厂实现;6. 装饰器也可用于类和类方法;7. 最佳实践包括保持装饰器职责单一、命名清晰、添加文档、处理错误、编写测试,并避免过度使用。

Python装饰器,简单来说,就是一种特殊的函数,它能接收一个函数作为输入,然后返回一个新的函数。这个新函数通常在原有函数的基础上,增加了额外的功能,比如日志记录、性能计时、权限检查等等,而这一切都不需要修改原始函数的代码。它让我们的代码更干净、更模块化,尤其是在处理那些跨多个函数但逻辑相似的任务时,简直是神器。本质上,它是高阶函数应用的一种优雅的语法糖。

装饰器的核心思想是“包裹”和“增强”。想象一下,你有一件很棒的衣服(原始函数),但你想让它防风防水(增加功能),你不需要改造衣服本身,而是给它套上一件高性能的外套(装饰器)。这件外套在保持衣服原有功能的同时,赋予了它新的属性。
在Python里,一个装饰器通常是一个函数,它接受一个函数作为参数,并返回一个新的函数。这个新的函数里面会调用原函数,并在调用前后执行一些额外的操作。
立即学习“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__}' 执行耗时: {end_time - start_time:.4f} 秒")
return result
return wrapper
# 使用装饰器
@timer
def long_running_task(n):
"""一个模拟长时间运行任务的函数"""
print(f"开始执行 long_running_task({n})...")
time.sleep(n)
print(f"long_running_task({n}) 执行完毕.")
return f"任务 {n} 完成"
# 调用被装饰的函数
long_running_task(2)
long_running_task(0.5)
# 实际上 @timer 等价于 long_running_task = timer(long_running_task)通过
@timer
long_running_task
timer
long_running_task
这里的“魔术”其实是Python闭包(closures)和函数作为一等公民的特性在幕后协同作用。当一个函数(比如
timer
wrapper
timer
wrapper
func

wrapper
wrapper
wrapper
一个不那么明显但非常重要的点是,当你使用装饰器后,被装饰函数的元数据(比如函数名
__name__
__doc__
wrapper
functools.wraps
wrapper
import time
from functools import wraps
def timer_with_wraps(func):
@wraps(func) # 使用 functools.wraps 来保留元数据
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_with_wraps
def another_task(x):
"""这是另一个模拟任务"""
time.sleep(x)
return f"任务 {x} 完成"
print(f"函数名: {another_task.__name__}")
print(f"文档: {another_task.__doc__}")
another_task(1)你会发现,加上
@wraps(func)
another_task.__name__
another_task
wrapper
要理解装饰器,就绕不开高阶函数(Higher-Order Functions, HOFs)。高阶函数是函数式编程的核心概念之一,它指的是满足以下至少一个条件的函数:
是不是听起来很耳熟?没错,装饰器完美符合这两个定义。一个装饰器(比如
timer
long_running_task
wrapper
Python中有很多内置的高阶函数,比如
map()
filter()
sorted()
key
# 经典的高阶函数示例:map
numbers = [1, 2, 3, 4]
squared_numbers = list(map(lambda x: x * x, numbers))
print(f"平方数列表: {squared_numbers}") # map 接受一个函数 (lambda) 和一个可迭代对象
# 装饰器就是这种思想的自然延伸
# 它将函数作为输入,再返回一个“增强版”的函数可以说,没有高阶函数的概念,就没有装饰器。装饰器是高阶函数在特定应用场景下的一种优雅且富有表现力的语法糖,它让代码的结构更加清晰,职责分离更加明确。理解高阶函数,就是理解装饰器背后的设计哲学。
虽然装饰器功能强大,但在使用过程中也确实有一些需要注意的地方,否则可能会踩坑。
常见陷阱:
元数据丢失: 前面已经提过,这是最常见的陷阱。不使用
functools.wraps
__name__
__doc__
wrapper
多重装饰器的顺序: 当一个函数被多个装饰器装饰时,它们的执行顺序是从下往上(离函数定义最近的先执行)。这意味着最上面的装饰器是最后被应用的。如果顺序不对,可能会导致意想不到的行为。
@decorator_b
@decorator_a
def my_func():
pass
# 实际执行顺序是 my_func = decorator_b(decorator_a(my_func))装饰器带参数: 如果你的装饰器需要接收参数,它就不能直接是一个函数了,而需要是一个返回装饰器(也就是一个高阶函数)的函数。这被称为“装饰器工厂”。
def repeat(num_times):
def decorator_repeat(func):
@wraps(func)
def wrapper(*args, **kwargs):
for _ in range(num_times):
func(*args, **kwargs)
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")这里
repeat
num_times
decorator_repeat
装饰类或方法: 装饰器不仅可以装饰函数,也可以装饰类或类中的方法。对于类方法(
@classmethod
@staticmethod
@property
最佳实践:
functools.wraps
try...except
掌握这些,你在Python的世界里运用装饰器就会更加得心应手,写出既优雅又健壮的代码。
以上就是Python装饰器有什么用?深入理解高阶函数的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号