Python装饰器完全指南
装饰器是Python最强大的特性之一.本文从基础语法到高级应用,带你全面掌握装饰器.
第1步:理解函数是一等公民
# Python中函数可以像变量一样传递
def greet(name):
return f"Hello, {name}!"
# 函数可以赋值给变量
say_hello = greet
print(say_hello("Alice")) # Hello, Alice!
# 函数可以作为参数
def execute(func, arg):
return func(arg)
execute(greet, "Bob") # Hello, Bob!
# 函数可以嵌套定义
def outer():
def inner():
return "I'm inner"
return inner
func = outer()
print(func()) # I'm inner
第2步:手写第一个装饰器
# 装饰器本质:接收函数作为参数,返回一个新函数
def my_decorator(func):
'''
装饰器函数
参数func: 被装饰的原始函数
返回: 包装后的新函数
'''
def wrapper(*args, **kwargs):
# 函数执行前的操作
print(f"准备执行: {func.__name__}")
# 调用原始函数
result = func(*args, **kwargs)
# 函数执行后的操作
print(f"执行完成: {func.__name__}")
return result
return wrapper
# 使用装饰器
@my_decorator
def say_hi():
print("Hi!")
# 等价于: say_hi = my_decorator(say_hi)
say_hi()
# 输出:
# 准备执行: say_hi
# Hi!
# 执行完成: say_hi
第3步:带参数的装饰器
# 装饰器本身需要参数时,需要三层嵌套
def repeat(times):
'''
让函数重复执行指定次数的装饰器
参数times: 重复执行次数
'''
def decorator(func):
def wrapper(*args, **kwargs):
results = []
for i in range(times):
print(f"第{i+1}次执行...")
result = func(*args, **kwargs)
results.append(result)
return results
return wrapper
return decorator
@repeat(times=3)
def greet(name):
return f"Hello {name}"
results = greet("World")
# 输出:
# 第1次执行...
# 第2次执行...
# 第3次执行...
# results = ['Hello World', 'Hello World', 'Hello World']
第4步:实用装饰器案例
import time
import functools
# 1. 计时装饰器
def timer(func):
'''计算函数执行时间'''
@functools.wraps(func) # 保留原函数元数据
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
print(f"{func.__name__} 执行耗时: {elapsed:.4f}秒")
return result
return wrapper
# 2. 缓存装饰器(简易版)
def memoize(func):
'''缓存函数结果,避免重复计算'''
cache = {}
@functools.wraps(func)
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
# 3. 重试装饰器
def retry(max_attempts=3, delay=1):
'''失败时自动重试'''
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise
print(f"第{attempt+1}次失败: {e},{delay}秒后重试...")
time.sleep(delay)
return wrapper
return decorator
# 使用示例
@timer
@memoize
def fibonacci(n):
'''计算斐波那契数列'''
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(30)) # 第一次较慢
print(fibonacci(30)) # 第二次从缓存读取,瞬间完成
第5步:类装饰器
# 用类实现装饰器
class CountCalls:
'''统计函数被调用次数'''
def __init__(self, func):
functools.update_wrapper(self, func)
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"{self.func.__name__} 被调用了 {self.count} 次")
return self.func(*args, **kwargs)
@CountCalls
def hello():
print("Hello!")
hello() # 被调用了 1 次
hello() # 被调用了 2 次
hello() # 被调用了 3 次
总结
装饰器是Python的语法糖,核心是高阶函数+闭包.掌握装饰器,能让你的代码更加简洁,可复用.
