Python 装饰器全攻略:从入门到精通的趣味之旅
内容简介
本系列文章是为 Python3 学习者精心设计的一套全面、实用的学习指南,旨在帮助读者从基础入门到项目实战,全面提升编程能力。文章结构由 5 个版块组成,内容层层递进,逻辑清晰。
- 基础速通:n 个浓缩提炼的核心知识点,夯实编程基础;
- 经典范例:10 个贴近实际的应用场景,深入理解 Python3 的编程技巧和应用方法;
- 避坑宝典:10 个典型错误解析,提供解决方案,帮助读者避免常见的编程陷阱;
- 水平考试:10 道测试题目,检验学习成果,附有标准答案,以便自我评估;
- 实战案例:3 个迷你项目开发,带领读者从需求分析到代码实现,掌握项目开发的完整流程。
无论你是 Python3 初学者,还是希望提升实战能力的开发者,本系列文章都能为你提供清晰的学习路径和实用的编程技巧,助你快速成长为 Python3 编程高手。
阅读建议
- 初学者:建议从 “基础速通” 开始,系统学习 Python3 的基础知识,然后通过 “经典范例” 和 “避坑宝典” 加深理解,最后通过 “水平考试” 和 “实战案例” 巩固所学内容;
- 有经验的开发者:可以直接跳转到 “经典范例” 和 “避坑宝典”,快速掌握 Python3 的高级应用技巧和常见错误处理方法,然后通过 “实战案例” 提升项目开发能力;
- 选择性学习:如果读者对某个特定主题感兴趣,可以直接选择相应版块学习。各版块内容既相互独立又逻辑关联,方便读者根据自身需求灵活选择;
- 测试与巩固:完成每个版块的学习后,建议通过 “水平考试” 检验学习效果,并通过 “实战案例” 将理论知识转化为实际技能;
- 项目实战优先:如果你更倾向于实战学习,可以直接从 “实战案例” 入手,边做边学,遇到问题再回溯相关知识点。
一、基础速通
Python的装饰器(Decorator)是一种用于修改或扩展函数或方法行为的工具。它本质上是一个函数,接受一个函数作为参数,并返回一个新的函数。装饰器通常用于在不修改原函数代码的情况下,增加额外的功能。
装饰器的作用
- 代码复用:可以将通用的功能(如日志记录、权限检查、性能测试等)封装在装饰器中,避免重复代码。
- 动态扩展功能:在不改变原函数的情况下,动态地为函数添加新功能。
- 简化代码:通过装饰器,可以将与核心逻辑无关的代码分离出来,使代码更清晰。
装饰器的基本语法
装饰器使用 @
符号,放在函数定义的上方。例如:
@decorator
def function():
pass
这等价于:
def function():
pass
function = decorator(function)
示例
1. 简单的装饰器
以下是一个简单的装饰器示例,用于打印函数的执行时间:
import time
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 example_function(n):
time.sleep(n)
print("函数执行完毕")
example_function(2)
输出:
函数执行完毕
example_function 执行时间: 2.0023秒
2. 带参数的装饰器
如果需要装饰器本身接受参数,可以再嵌套一层函数:
def repeat(num_times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def say_hello():
print("Hello!")
say_hello()
输出:
Hello!
Hello!
Hello!
3. 类装饰器
装饰器也可以是类,只要实现 __call__
方法即可:
class CountCalls:
def __init__(self, func):
self.func = func
self.call_count = 0
def __call__(self, *args, **kwargs):
self.call_count += 1
print(f"函数 {self.func.__name__} 被调用了 {self.call_count} 次")
return self.func(*args, **kwargs)
@CountCalls
def greet():
print("Hello, World!")
greet()
greet()
输出:
函数 greet 被调用了 1 次
Hello, World!
函数 greet 被调用了 2 次
Hello, World!
小结
装饰器是Python中非常强大的工具,可以用于日志记录、权限验证、性能测试、缓存等场景。通过装饰器,可以保持代码的简洁性和可维护性。
二、经典范例
以下是 10 个装饰器应用的经典范例:
1. 日志记录
记录函数的调用信息。
def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"调用函数: {func.__name__}, 参数: {args}, {kwargs}")
result = func(*args, **kwargs)
print(f"函数 {func.__name__} 执行完毕")
return result
return wrapper
@log_decorator
def add(a, b):
return a + b
print(add(3, 5))
输出:
调用函数: add, 参数: (3, 5), {}
函数 add 执行完毕
8
说明: 记录函数的调用和参数,方便调试和追踪。
2. 性能测试
测量函数的执行时间。
import time
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 slow_function():
time.sleep(2)
slow_function()
输出:
slow_function 执行时间: 2.0023秒
说明: 用于测试函数的性能,找出耗时操作。
3. 权限验证
检查用户是否有权限调用函数。
def auth_decorator(func):
def wrapper(*args, **kwargs):
user = kwargs.get("user", "guest")
if user == "admin":
return func(*args, **kwargs)
else:
return "权限不足"
return wrapper
@auth_decorator
def delete_file(user):
return "文件已删除"
print(delete_file(user="admin"))
print(delete_file(user="guest"))
输出:
文件已删除
权限不足
说明: 用于限制某些功能的访问权限。
4. 缓存结果
缓存函数的返回值,避免重复计算。
def cache_decorator(func):
cache = {}
def wrapper(*args):
if args in cache:
print("从缓存中获取结果")
return cache[args]
result = func(*args)
cache[args] = result
return result
return wrapper
@cache_decorator
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
print(fibonacci(10))
输出:
55
从缓存中获取结果
55
说明: 适用于计算密集型函数,提升性能。
5. 重试机制
在函数失败时自动重试。
import random
def retry_decorator(max_retries=3):
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(max_retries):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"重试 {i+1}/{max_retries}: {e}")
raise Exception("重试次数用尽")
return wrapper
return decorator
@retry_decorator(max_retries=3)
def unstable_function():
if random.random() < 0.5:
raise Exception("随机失败")
return "成功"
print(unstable_function())
输出:
重试 1/3: 随机失败
成功
说明: 用于处理可能失败的操作,如网络请求。
6. 单例模式
确保一个类只有一个实例。
def singleton_decorator(cls):
instances = {}
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton_decorator
class Database:
def __init__(self):
print("数据库连接已创建")
db1 = Database()
db2 = Database()
print(db1 is db2)
输出:
数据库连接已创建
True
说明: 用于确保全局只有一个实例。
7. 输入验证
验证函数的输入参数。
def validate_input(func):
def wrapper(*args, **kwargs):
for arg in args:
if not isinstance(arg, int):
raise ValueError("参数必须是整数")
return func(*args, **kwargs)
return wrapper
@validate_input
def add(a, b):
return a + b
print(add(3, 5))
# print(add(3, "5")) # 会抛出 ValueError
输出:
8
说明: 确保函数输入符合预期。
8. 限制调用频率
限制函数的调用频率。
import time
def rate_limit_decorator(max_calls, period):
def decorator(func):
calls = []
def wrapper(*args, **kwargs):
now = time.time()
calls.append(now)
calls[:] = [call for call in calls if now - call < period]
if len(calls) > max_calls:
raise Exception("调用频率过高")
return func(*args, **kwargs)
return wrapper
return decorator
@rate_limit_decorator(max_calls=2, period=5)
def api_call():
return "API 调用成功"
print(api_call())
print(api_call())
# print(api_call()) # 会抛出异常
输出:
API 调用成功
API 调用成功
说明: 用于限制 API 或资源的访问频率。
9. 事务管理
确保函数在事务中执行。
def transaction_decorator(func):
def wrapper(*args, **kwargs):
print("事务开始")
try:
result = func(*args, **kwargs)
print("事务提交")
return result
except Exception as e:
print("事务回滚")
raise e
return wrapper
@transaction_decorator
def transfer_money():
print("转账操作")
transfer_money()
输出:
事务开始
转账操作
事务提交
说明: 用于数据库操作或需要事务管理的场景。
10. 函数注册
将函数注册到某个集合中。
functions = []
def register_decorator(func):
functions.append(func)
return func
@register_decorator
def func1():
print("函数 1")
@register_decorator
def func2():
print("函数 2")
for func in functions:
func()
输出:
函数 1
函数 2
说明: 用于插件系统或事件驱动编程。
小结
以上是 10 个经典的使用场景,涵盖了装饰器的多种用途。每个示例都附有测试案例和执行结果,方便理解和使用。
三、避坑宝典
在编写或使用 Python 装饰器时,可能会遇到一些典型的错误。以下是 10 种常见错误,分析出错原因并提供纠正方法,同时通过代码示例进行演示和说明。
1. 忘记调用被装饰的函数
错误原因:在装饰器中忘记调用被装饰的函数。
错误代码:
def decorator(func):
def wrapper():
print("装饰器逻辑")
# 忘记调用 func()
return wrapper
@decorator
def my_function():
print("函数逻辑")
my_function()
输出:
装饰器逻辑
纠正方法:确保在装饰器中调用被装饰的函数。
正确代码:
def decorator(func):
def wrapper():
print("装饰器逻辑")
func() # 调用被装饰的函数
return wrapper
@decorator
def my_function():
print("函数逻辑")
my_function()
输出:
装饰器逻辑
函数逻辑
2. 装饰器未返回包装函数
错误原因:装饰器没有返回包装函数。
错误代码:
def decorator(func):
print("装饰器逻辑")
# 忘记返回 wrapper
@decorator
def my_function():
print("函数逻辑")
my_function()
输出:
装饰器逻辑
TypeError: 'NoneType' object is not callable
纠正方法:确保装饰器返回包装函数。
正确代码:
def decorator(func):
def wrapper():
print("装饰器逻辑")
func()
return wrapper # 返回 wrapper
@decorator
def my_function():
print("函数逻辑")
my_function()
输出:
装饰器逻辑
函数逻辑
3. 未正确处理函数参数
错误原因:装饰器未正确处理被装饰函数的参数。
错误代码:
def decorator(func):
def wrapper():
print("装饰器逻辑")
func() # 未传递参数
return wrapper
@decorator
def my_function(a, b):
print(f"a + b = {a + b}")
my_function(1, 2)
输出:
TypeError: wrapper() takes 0 positional arguments but 2 were given
纠正方法:使用 *args
和 **kwargs
传递参数。
正确代码:
def decorator(func):
def wrapper(*args, **kwargs):
print("装饰器逻辑")
func(*args, **kwargs) # 正确传递参数
return wrapper
@decorator
def my_function(a, b):
print(f"a + b = {a + b}")
my_function(1, 2)
输出:
装饰器逻辑
a + b = 3
4. 装饰器破坏了原函数的元信息
错误原因:装饰器覆盖了原函数的 __name__
和 __doc__
等元信息。
错误代码:
def decorator(func):
def wrapper():
print("装饰器逻辑")
func()
return wrapper
@decorator
def my_function():
"""这是一个示例函数"""
print("函数逻辑")
print(my_function.__name__) # 输出 wrapper
print(my_function.__doc__) # 输出 None
输出:
wrapper
None
纠正方法:使用 functools.wraps
保留元信息。
正确代码:
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper():
print("装饰器逻辑")
func()
return wrapper
@decorator
def my_function():
"""这是一个示例函数"""
print("函数逻辑")
print(my_function.__name__) # 输出 my_function
print(my_function.__doc__) # 输出 这是一个示例函数
输出:
my_function
这是一个示例函数
5. 装饰器嵌套顺序错误
错误原因:多个装饰器的嵌套顺序错误,导致逻辑混乱。
错误代码:
def decorator1(func):
def wrapper():
print("装饰器 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("装饰器 2")
func()
return wrapper
@decorator1
@decorator2
def my_function():
print("函数逻辑")
my_function()
输出:
装饰器 1
装饰器 2
函数逻辑
纠正方法:调整装饰器的嵌套顺序。
正确代码:
@decorator2
@decorator1
def my_function():
print("函数逻辑")
my_function()
输出:
装饰器 2
装饰器 1
函数逻辑
6. 装饰器未正确处理返回值
错误原因:装饰器未返回被装饰函数的返回值。
错误代码:
def decorator(func):
def wrapper():
print("装饰器逻辑")
func() # 未返回 func() 的结果
return wrapper
@decorator
def my_function():
return "函数返回值"
print(my_function())
输出:
装饰器逻辑
None
纠正方法:返回被装饰函数的结果。
正确代码:
def decorator(func):
def wrapper():
print("装饰器逻辑")
return func() # 返回 func() 的结果
return wrapper
@decorator
def my_function():
return "函数返回值"
print(my_function())
输出:
装饰器逻辑
函数返回值
7. 装饰器未正确处理异常
错误原因:装饰器未正确处理被装饰函数抛出的异常。
错误代码:
def decorator(func):
def wrapper():
print("装饰器逻辑")
func() # 未捕获异常
return wrapper
@decorator
def my_function():
raise ValueError("函数出错")
my_function()
输出:
装饰器逻辑
ValueError: 函数出错
纠正方法:捕获并处理异常。
正确代码:
def decorator(func):
def wrapper():
print("装饰器逻辑")
try:
func()
except ValueError as e:
print(f"捕获异常: {e}")
return wrapper
@decorator
def my_function():
raise ValueError("函数出错")
my_function()
输出:
装饰器逻辑
捕获异常: 函数出错
8. 装饰器未正确处理类方法
错误原因:装饰器未正确处理类方法的 self
参数。
错误代码:
def decorator(func):
def wrapper():
print("装饰器逻辑")
func() # 未传递 self
return wrapper
class MyClass:
@decorator
def my_method(self):
print("方法逻辑")
obj = MyClass()
obj.my_method()
输出:
TypeError: wrapper() takes 0 positional arguments but 1 was given
纠正方法:使用 *args
和 **kwargs
传递 self
。
正确代码:
def decorator(func):
def wrapper(*args, **kwargs):
print("装饰器逻辑")
func(*args, **kwargs)
return wrapper
class MyClass:
@decorator
def my_method(self):
print("方法逻辑")
obj = MyClass()
obj.my_method()
输出:
装饰器逻辑
方法逻辑
9. 装饰器未正确处理静态方法
错误原因:装饰器未正确处理静态方法的特性。
错误代码:
def decorator(func):
def wrapper():
print("装饰器逻辑")
func()
return wrapper
class MyClass:
@decorator
@staticmethod
def my_method():
print("静态方法逻辑")
MyClass.my_method()
输出:
TypeError: 'staticmethod' object is not callable
纠正方法:将装饰器放在 @staticmethod
上方。
正确代码:
class MyClass:
@staticmethod
@decorator
def my_method():
print("静态方法逻辑")
MyClass.my_method()
输出:
装饰器逻辑
静态方法逻辑
10. 装饰器未正确处理类装饰器
错误原因:类装饰器未实现 __call__
方法。
错误代码:
class Decorator:
def __init__(self, func):
self.func = func
@Decorator
def my_function():
print("函数逻辑")
my_function()
输出:
TypeError: 'Decorator' object is not callable
纠正方法:实现 __call__
方法。
正确代码:
class Decorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("装饰器逻辑")
return self.func(*args, **kwargs)
@Decorator
def my_function():
print("函数逻辑")
my_function()
输出:
装饰器逻辑
函数逻辑
四、水平考试
本试卷包含选择题 15 题、填空题 10 题和编程题 5 题,共计 30 道题,满分 100 分。每道题后附有正确答案和解析。
选择题(每题2分,共30分)
-
装饰器的本质是什么?
A. 类
B. 函数
C. 模块
D. 变量
答案:B
解析:装饰器本质上是函数,用于修改或扩展其他函数的行为。 -
以下哪个符号用于装饰器语法?
A.#
B.@
C.$
D.&
答案:B
解析:@
符号用于装饰器语法。 -
以下代码的输出是什么?
def decorator(func): def wrapper(): print("装饰器逻辑") func() return wrapper @decorator def my_function(): print("函数逻辑") my_function()
A. 装饰器逻辑
B. 函数逻辑
C. 装饰器逻辑 函数逻辑
D. 无输出
答案:C
解析:装饰器会先执行wrapper
中的逻辑,再调用原函数。 -
以下哪个函数可以保留被装饰函数的元信息?
A.functools.wraps
B.functools.partial
C.functools.reduce
D.functools.lru_cache
答案:A
解析:functools.wraps
用于保留被装饰函数的元信息。 -
以下代码的输出是什么?
def decorator(func): def wrapper(*args, **kwargs): return func(*args, **kwargs) + 1 return wrapper @decorator def add(a, b): return a + b print(add(2, 3))
A. 5
B. 6
C. 7
D. 8
答案:B
解析:装饰器对函数结果进行了加1操作。 -
以下哪个场景适合使用装饰器?
A. 计算两个数的和
B. 记录函数的执行时间
C. 定义类属性
D. 创建列表
答案:B
解析:装饰器常用于记录日志、性能测试等场景。 -
以下代码的输出是什么?
def decorator(func): def wrapper(): print("装饰器逻辑") return wrapper @decorator def my_function(): print("函数逻辑") my_function()
A. 装饰器逻辑
B. 函数逻辑
C. 装饰器逻辑 函数逻辑
D. 无输出
答案:A
解析:装饰器中未调用原函数,因此只执行了wrapper
的逻辑。 -
以下哪个装饰器可以缓存函数的结果?
A.@functools.lru_cache
B.@functools.wraps
C.@staticmethod
D.@property
答案:A
解析:@functools.lru_cache
用于缓存函数的结果。 -
以下代码的输出是什么?
def decorator(func): def wrapper(): return func().upper() return wrapper @decorator def greet(): return "hello" print(greet())
A. hello
B. HELLO
C. Hello
D. 无输出
答案:B
解析:装饰器将函数返回值转换为大写。 -
以下哪个装饰器用于限制函数调用频率?
A.@rate_limit
B.@cache
C.@retry
D.@log
答案:A
解析:@rate_limit
用于限制函数调用频率。 -
以下代码的输出是什么?
def decorator(func): def wrapper(): return func() + " world" return wrapper @decorator def greet(): return "hello" print(greet())
A. hello
B. world
C. hello world
D. 无输出
答案:C
解析:装饰器在函数返回值后添加了 " world"。 -
以下哪个装饰器用于将方法定义为类方法?
A.@staticmethod
B.@classmethod
C.@property
D.@abstractmethod
答案:B
解析:@classmethod
用于定义类方法。 -
以下代码的输出是什么?
def decorator(func): def wrapper(): return func() * 2 return wrapper @decorator def get_value(): return 5 print(get_value())
A. 5
B. 10
C. 25
D. 无输出
答案:B
解析:装饰器将函数返回值乘以2。 -
以下哪个装饰器用于将方法定义为静态方法?
A.@staticmethod
B.@classmethod
C.@property
D.@abstractmethod
答案:A
解析:@staticmethod
用于定义静态方法。 -
以下代码的输出是什么?
def decorator(func): def wrapper(): return func() + 10 return wrapper @decorator def get_value(): return 5 print(get_value())
A. 5
B. 10
C. 15
D. 无输出
答案:C
解析:装饰器在函数返回值后加了10。
填空题(每题3分,共30分)
-
装饰器的本质是一个______。
答案:函数 -
使用
@
符号调用装饰器时,装饰器函数必须返回一个______。
答案:函数 -
functools.wraps
的作用是保留被装饰函数的______。
答案:元信息 -
以下代码的输出是______。
def decorator(func): def wrapper(): return func() + 1 return wrapper @decorator def get_value(): return 5 print(get_value())
答案:6
-
以下代码的输出是______。
def decorator(func): def wrapper(): return func().upper() return wrapper @decorator def greet(): return "hello" print(greet())
答案:HELLO
-
以下代码的输出是______。
def decorator(func): def wrapper(): return func() * 2 return wrapper @decorator def get_value(): return 3 print(get_value())
答案:6
-
以下代码的输出是______。
def decorator(func): def wrapper(): return func() + " world" return wrapper @decorator def greet(): return "hello" print(greet())
答案:hello world
-
以下代码的输出是______。
def decorator(func): def wrapper(): return func() + 10 return wrapper @decorator def get_value(): return 5 print(get_value())
答案:15
-
以下代码的输出是______。
def decorator(func): def wrapper(): return func() + 1 return wrapper @decorator def get_value(): return 5 print(get_value())
答案:6
-
以下代码的输出是______。
def decorator(func): def wrapper(*args): return func(*args).upper() return wrapper @decorator def greet(username): return "hello" + ' ' + username + '!' print(greet("roger"))
答案:HELLO ROGER!
编程题(每题8分,共40分)
-
编写一个装饰器,记录函数的执行时间并打印。
答案:import time 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 my_function(): time.sleep(2) my_function()
-
编写一个装饰器,缓存函数的结果以避免重复计算。
答案:def cache_decorator(func): cache = {} def wrapper(*args): if args in cache: return cache[args] result = func(*args) cache[args] = result return result return wrapper @cache_decorator def fibonacci(n): if n < 2: return n return fibonacci(n-1) + fibonacci(n-2) print(fibonacci(10))
-
编写一个装饰器,限制函数的调用频率(例如每秒最多调用一次)。
答案:import time def rate_limit_decorator(max_calls, period): calls = [] def decorator(func): def wrapper(*args, **kwargs): now = time.time() calls.append(now) calls[:] = [call for call in calls if now - call < period] if len(calls) > max_calls: raise Exception("调用频率过高") return func(*args, **kwargs) return wrapper return decorator @rate_limit_decorator(max_calls=1, period=1) def my_function(): print("函数调用") my_function()
-
编写一个装饰器,实现函数的重试机制(例如失败后重试3次)。
答案:import random def retry_decorator(max_retries=3): def decorator(func): def wrapper(*args, **kwargs): for i in range(max_retries): try: return func(*args, **kwargs) except Exception as e: print(f"重试 {i+1}/{max_retries}: {e}") raise Exception("重试次数用尽") return wrapper return decorator @retry_decorator(max_retries=3) def unstable_function(): if random.random() < 0.5: raise Exception("随机失败") return "成功" print(unstable_function())
-
编写一个装饰器,将函数的返回值格式化为 JSON 字符串。
答案:import json def json_decorator(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) return json.dumps(result) return wrapper @json_decorator def my_function(): return {"name": "Alice", "age": 30} print(my_function())
总分:100分
希望这套试卷能帮助你巩固 Python 装饰器的知识!
五、实战案例
以下是 3 个使用 Python 装饰器的综合应用项目,这些项目具有新颖性、前瞻性和实用性。每个项目都包含完整的代码、解释说明、测试案例和执行结果。
项目 1:API 请求限流器
描述:实现一个装饰器,限制 API 请求的频率,防止服务器过载。
代码实现
import time
def rate_limiter(max_calls, period):
"""
限制函数调用频率的装饰器。
:param max_calls: 每个时间段内允许的最大调用次数。
:param period: 时间段(秒)。
"""
calls = []
def decorator(func):
def wrapper(*args, **kwargs):
now = time.time()
# 移除超时的调用记录
calls[:] = [call for call in calls if now - call < period]
if len(calls) >= max_calls:
raise Exception("请求频率过高,请稍后再试")
calls.append(now)
return func(*args, **kwargs)
return wrapper
return decorator
# 测试案例
@rate_limiter(max_calls=3, period=5)
def api_request():
print("API 请求成功")
# 模拟请求
for i in range(5):
try:
api_request()
except Exception as e:
print(e)
time.sleep(1)
执行结果
API 请求成功
API 请求成功
API 请求成功
请求频率过高,请稍后再试
请求频率过高,请稍后再试
说明:该装饰器限制每 5 秒内最多调用 3 次 API,超过限制会抛出异常。
项目 2:函数结果缓存
描述:实现一个装饰器,缓存函数的结果,避免重复计算。
代码实现
def cache_decorator(func):
"""
缓存函数结果的装饰器。
"""
cache = {}
def wrapper(*args):
if args in cache:
print("从缓存中获取结果")
return cache[args]
result = func(*args)
cache[args] = result
return result
return wrapper
# 测试案例
@cache_decorator
def fibonacci(n):
"""
计算斐波那契数列。
"""
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
print(fibonacci(10))
执行结果
55
从缓存中获取结果
55
说明:该装饰器缓存了斐波那契数列的计算结果,避免重复计算。
项目 3:异步任务重试机制
描述:实现一个装饰器,为异步任务提供重试机制。
代码实现
import asyncio
import random
def retry_decorator(max_retries=3):
"""
为异步函数提供重试机制的装饰器。
:param max_retries: 最大重试次数。
"""
def decorator(func):
async def wrapper(*args, **kwargs):
for i in range(max_retries):
try:
return await func(*args, **kwargs)
except Exception as e:
print(f"重试 {i+1}/{max_retries}: {e}")
await asyncio.sleep(1)
raise Exception("重试次数用尽")
return wrapper
return decorator
# 测试案例
@retry_decorator(max_retries=3)
async def unstable_task():
if random.random() < 0.5:
raise Exception("任务失败")
return "任务成功"
async def main():
try:
result = await unstable_task()
print(result)
except Exception as e:
print(e)
asyncio.run(main())
执行结果
重试 1/3: 任务失败
任务成功
说明:该装饰器为异步任务提供了重试机制,失败后最多重试 3 次。