Python装饰器完全指南:从入门到实战

# Python装饰器完全指南:从入门到实战

## 什么是装饰器?

装饰器(Decorator)是Python中一种强大的语法特性,它允许我们在不修改原函数代码的前提下,动态地给函数添加额外的功能。你可以把装饰器想象成一个"包装纸",包裹在函数外面,改变其行为但不改变其本质。

## 基础概念

### 函数是一等公民

在理解装饰器之前,首先要明白Python中的函数是一等公民(first-class object),这意味着:
- 函数可以赋值给变量
- 函数可以作为参数传递给其他函数
- 函数可以作为其他函数的返回值

``python
def hello():
return "Hello, World!"

greet = hello # 函数赋值给变量
print(greet()) # 输出: Hello, World!
`

### 嵌套函数

Python支持在函数内部定义函数:

`python
def outer():
def inner():
return "I'm inside"
return inner

func = outer()
print(func()) # 输出: I'm inside
`

## 简单的装饰器实现

让我们从一个简单的例子开始:

`python
import functools

def my_decorator(func):
@functools.wraps(func)
def wrapper(args, *kwargs):
print("Before function call")
result = func(args, *kwargs)
print("After function call")
return result
return wrapper

@my_decorator
def say_hello(name):
print(f"Hello, {name}!")

say_hello("Alice")
`

输出:

`
Before function call
Hello, Alice!
After function call
`

## 常见装饰器应用场景

### 1. 日志记录

`python
import logging
import functools

def log_decorator(func):
@functools.wraps(func)
def wrapper(args, *kwargs):
logging.info(f'Calling {func.__name__}')
result = func(args, *kwargs)
logging.info(f'{func.__name__} returned {result}')
return result
return wrapper
`

### 2. 性能计时

`python
import time
import functools

def timer(func):
@functools.wraps(func)
def wrapper(args, *kwargs):
start = time.time()
result = func(args, *kwargs)
end = time.time()
print(f'{func.__name__} took {end - start:.4f} seconds')
return result
return wrapper
`

### 3. 权限验证

`python
def require_login(func):
@functools.wraps(func)
def wrapper(args, *kwargs):
user = get_current_user()
if not user.is_authenticated:
raise PermissionError("Please login first")
return func(args, *kwargs)
return wrapper
`

### 4. 缓存结果

`python
import functools

def cache(func):
cache_dict = {}

@functools.wraps(func)
def wrapper(*args):
if args not in cache_dict:
cache_dict[args] = func(*args)
return cache_dict[args]

return wrapper
`

## 带参数的装饰器

有时候我们需要给装饰器传递参数:

`python
import functools

def repeat(times):
def decorator(func):
@functools.wraps(func)
def wrapper(args, *kwargs):
for _ in range(times):
result = func(args, *kwargs)
return result
return wrapper
return decorator

@repeat(3)
def greet(name):
print(f"Hello, {name}!")

greet("Bob") # 会打印三次
`

## 多个装饰器叠加

Python允许我们将多个装饰器应用到同一个函数上:

`python
@decorator1
@decorator2
def my_function():
pass

# 等价于
my_function = decorator1(decorator2(my_function))
`

执行顺序是从下到上,即先执行最下面的装饰器。

## 使用内置装饰器

### @property

`python
class Circle:
def __init__(self, radius):
self._radius = radius

@property
def radius(self):
return self._radius

@property
def area(self):
return 3.14159 self._radius * 2
`

### @staticmethod 和 @classmethod

`python
class MathUtils:
@staticmethod
def add(a, b):
return a + b

@classmethod
def from_string(cls, value):
return cls(int(value))
`

## 最佳实践

1. 始终使用 @functools.wraps`:保留原函数的元信息
2. 避免过度使用:装饰器应该用于横切关注点
3. 保持简单:装饰器的逻辑应该简洁明了
4. 注意装饰器顺序:多个装饰器时,顺序会影响最终行为
5. 文档化:为自定义装饰器编写清晰的文档字符串

## 总结

装饰器是Python中非常灵活且强大的工具,掌握它可以让你写出更加优雅、可维护的代码。无论是日志记录、性能监控、权限控制还是缓存优化,装饰器都能提供优雅的解决方案。

记住,装饰器的核心思想是:不修改原有代码,通过包装来增强功能。这是Python"开放封闭原则"的完美体现。

目录