1. 装饰器与高阶函数概述
Python中的装饰器和高阶函数是函数式编程的重要概念,它们让代码更加灵活和可复用。装饰器本质上是一个接受函数作为参数并返回新函数的函数,而高阶函数则是能够接受函数作为参数或返回函数作为结果的函数。
装饰器在Python中广泛用于日志记录、性能测试、权限校验等场景,是Python元编程的重要工具。
2. 高阶函数详解
2.1 什么是高阶函数
高阶函数是指满足以下任一条件的函数:
- 接受一个或多个函数作为参数
- 返回一个函数作为结果
Python内置的高阶函数包括map()、filter()、reduce()等。
python复制# map函数示例
numbers = [1, 2, 3]
squared = list(map(lambda x: x**2, numbers))
print(squared) # 输出: [1, 4, 9]
2.2 常见高阶函数应用
2.2.1 map函数实现
map函数将一个函数应用于可迭代对象的每个元素:
python复制def my_map(func, iterable):
result = []
for item in iterable:
result.append(func(item))
return result
2.2.2 filter函数原理
filter函数根据条件筛选可迭代对象中的元素:
python复制def my_filter(func, iterable):
return [item for item in iterable if func(item)]
2.2.3 reduce函数工作方式
reduce函数对序列元素进行累积计算:
python复制from functools import reduce
def my_reduce(func, sequence, initial=None):
it = iter(sequence)
if initial is None:
value = next(it)
else:
value = initial
for element in it:
value = func(value, element)
return value
3. 装饰器深入解析
3.1 装饰器基础语法
装饰器使用@符号表示,本质上是一个语法糖:
python复制def decorator(func):
def wrapper(*args, **kwargs):
print("Before function call")
result = func(*args, **kwargs)
print("After function call")
return result
return wrapper
@decorator
def greet(name):
print(f"Hello, {name}!")
# 等价于
# greet = decorator(greet)
3.2 带参数的装饰器
装饰器也可以接受参数,需要额外嵌套一层函数:
python复制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(num_times=3)
def say_hello():
print("Hello!")
say_hello()
3.3 类装饰器实现
装饰器也可以使用类来实现:
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"Call {self.num_calls} of {self.func.__name__}")
return self.func(*args, **kwargs)
@CountCalls
def example():
print("Example function")
example()
example()
4. 装饰器高级应用
4.1 保留函数元信息
使用functools.wraps保留原始函数的元信息:
python复制from functools import wraps
def logged(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
@logged
def add(x, y):
"""Add two numbers"""
return x + y
print(add.__name__) # 输出: add
print(add.__doc__) # 输出: Add two numbers
4.2 多个装饰器叠加
装饰器可以叠加使用,执行顺序从下往上:
python复制def decorator1(func):
def wrapper():
print("Decorator 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("Decorator 2")
func()
return wrapper
@decorator1
@decorator2
def my_function():
print("Original function")
my_function()
4.3 装饰器在Web框架中的应用
装饰器在Flask等Web框架中广泛使用:
python复制from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "Hello, World!"
# 等效于
# home = app.route('/')(home)
5. 常见问题与解决方案
5.1 装饰器导致函数签名改变
问题:使用装饰器后,函数的__name__和__doc__等属性会被覆盖。
解决方案:使用functools.wraps装饰器:
python复制from functools import wraps
def preserve_metadata(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
5.2 装饰器与类方法的兼容性
问题:装饰器在类方法上使用时,可能无法正确处理self参数。
解决方案:确保装饰器能正确处理类方法的第一个参数:
python复制def method_decorator(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
print(f"Calling {func.__name__} on {self}")
return func(self, *args, **kwargs)
return wrapper
class MyClass:
@method_decorator
def my_method(self):
pass
5.3 装饰器性能优化
问题:装饰器会增加函数调用开销。
优化建议:
- 尽量减少装饰器内部的复杂逻辑
- 对于性能关键路径,考虑将装饰器逻辑移到函数内部
- 使用lru_cache缓存装饰器结果
python复制from functools import lru_cache
@lru_cache(maxsize=128)
def expensive_function(x):
# 复杂计算
return x * x
6. 实际应用案例
6.1 计时装饰器
python复制import time
from functools import wraps
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f"{func.__name__} took {end - start:.4f} seconds")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
6.2 权限验证装饰器
python复制def requires_auth(func):
@wraps(func)
def wrapper(*args, **kwargs):
if not is_authenticated():
raise PermissionError("Authentication required")
return func(*args, **kwargs)
return wrapper
@requires_auth
def sensitive_operation():
pass
6.3 重试机制装饰器
python复制import time
from functools import wraps
def retry(max_attempts=3, delay=1):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
attempts = 0
while attempts < max_attempts:
try:
return func(*args, **kwargs)
except Exception as e:
attempts += 1
if attempts == max_attempts:
raise
time.sleep(delay)
return wrapper
return decorator
@retry(max_attempts=5, delay=2)
def unreliable_api_call():
pass
在实际项目中,装饰器和高阶函数可以显著提高代码的可读性和可维护性。掌握这些概念后,你会发现Python代码可以写得更加优雅和高效。
