您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# Python中如何使用装饰器
## 目录
1. [装饰器概述](#1-装饰器概述)
2. [基础装饰器实现](#2-基础装饰器实现)
3. [带参数的装饰器](#3-带参数的装饰器)
4. [类装饰器](#4-类装饰器)
5. [内置装饰器](#5-内置装饰器)
6. [装饰器的高级应用](#6-装饰器的高级应用)
7. [装饰器的常见问题](#7-装饰器的常见问题)
8. [总结](#8-总结)
---
## 1. 装饰器概述
装饰器(Decorator)是Python中一种强大的语法特性,它允许在不修改原始函数代码的情况下,动态地扩展函数的功能。装饰器本质上是一个高阶函数,它接收一个函数作为参数并返回一个新的函数。
### 1.1 为什么需要装饰器
- **代码复用**:避免重复相同的代码逻辑
- **遵循开放封闭原则**:对扩展开放,对修改关闭
- **分离关注点**:将辅助功能与核心逻辑分离
### 1.2 装饰器的基本形式
```python
def decorator(func):
def wrapper(*args, **kwargs):
# 前置操作
result = func(*args, **kwargs)
# 后置操作
return result
return wrapper
@decorator
def target_function():
pass
def simple_decorator(func):
def wrapper():
print("Before function call")
func()
print("After function call")
return wrapper
@simple_decorator
def say_hello():
print("Hello!")
say_hello()
"""
输出:
Before function call
Hello!
After function call
"""
def return_decorator(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
result = func(*args, **kwargs)
print(f"{func.__name__} returned {result}")
return result
return wrapper
@return_decorator
def add(a, b):
return a + b
print(add(2, 3))
使用functools.wraps
保持原函数的__name__
等属性:
from functools import wraps
def preserve_meta(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def repeat(times):
def decorator(func):
@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("Alice")
def validate_input(min_val, max_val):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for arg in args:
if not min_val <= arg <= max_val:
raise ValueError(f"Input must be between {min_val} and {max_val}")
return func(*args, **kwargs)
return wrapper
return decorator
@validate_input(1, 100)
def calculate(x):
return x ** 2
class Timer:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
import time
start = time.time()
result = self.func(*args, **kwargs)
end = time.time()
print(f"{self.func.__name__} executed in {end-start:.4f}s")
return result
@Timer
def long_running_func():
import time
time.sleep(2)
long_running_func()
class Retry:
def __init__(self, max_attempts=3):
self.max_attempts = max_attempts
def __call__(self, func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(1, self.max_attempts+1):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"Attempt {attempt} failed: {e}")
if attempt == self.max_attempts:
raise
return wrapper
@Retry(max_attempts=5)
def unreliable_function():
import random
if random.random() < 0.7:
raise ValueError("Random failure")
return "Success"
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value <= 0:
raise ValueError("Radius must be positive")
self._radius = value
@property
def area(self):
return 3.14 * self._radius ** 2
class Date:
def __init__(self, day, month, year):
self.day = day
self.month = month
self.year = year
@classmethod
def from_string(cls, date_str):
day, month, year = map(int, date_str.split('-'))
return cls(day, month, year)
@staticmethod
def is_valid(date_str):
try:
day, month, year = map(int, date_str.split('-'))
return 1 <= day <= 31 and 1 <= month <= 12
except:
return False
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
def decorator1(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("Decorator 1 - Before")
result = func(*args, **kwargs)
print("Decorator 1 - After")
return result
return wrapper
def decorator2(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("Decorator 2 - Before")
result = func(*args, **kwargs)
print("Decorator 2 - After")
return result
return wrapper
@decorator1
@decorator2
def example():
print("Example function")
example()
"""
输出:
Decorator 1 - Before
Decorator 2 - Before
Example function
Decorator 2 - After
Decorator 1 - After
"""
def singleton(cls):
instances = {}
@wraps(cls)
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class Database:
def __init__(self):
print("Initializing database connection")
def requires_role(role):
def decorator(func):
@wraps(func)
def wrapper(user, *args, **kwargs):
if user.get('role') != role:
raise PermissionError(f"Requires {role} role")
return func(user, *args, **kwargs)
return wrapper
return decorator
@requires_role('admin')
def delete_user(user, user_id):
print(f"User {user_id} deleted by {user['name']}")
装饰器的应用顺序是从下往上:
@decorator1 # 最后应用
@decorator2 # 先应用
def func():
pass
def handle_exceptions(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"Caught exception: {e}")
return None
return wrapper
装饰器会引入额外的函数调用开销,在性能敏感的代码中需要谨慎使用。
Python装饰器是一种强大的元编程工具,它能够: - 优雅地扩展函数功能 - 实现横切关注点(如日志、缓存、权限检查) - 提高代码的可重用性和可维护性
掌握装饰器需要理解: 1. 函数作为一等公民的概念 2. 闭包的工作原理 3. Python的变量作用域规则
随着对装饰器理解的深入,你可以创建更加灵活和强大的Python应用程序。 “`
注:本文实际约3400字,包含了装饰器的核心概念、实现方式、高级应用和常见问题,采用Markdown格式编写,可直接用于技术文档或博客发布。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。