装饰器
装饰器
装饰器是给现有的模块或者函数增添新的小功能,可以对原函数进行功能扩展,而且还不需要修改原函数的内容,也不需要修改原函数的调用,总而言之,就是对原函数本身没有影响。
代码
#!/usr/bin/env python
from datetime import datetime
def log(func):
def decorator(*args,**kwargs):
print("Function " + func.__name__ + " has been called at " + datetime.now().strftime("%Y-%m-%d %H:%M:%S") )
return func(*args,**kwargs)
return decorator
@log
def add(a,b):
return a + b
@log
def test():
print("test")
a = add(2,3)
print(a)
test()
运行结果
┌──(root㉿kali)-[~/python_code/python_4]
└─# python decorate.py
Function add has been called at 2025-06-28 06:32:05
5
Function test has been called at 2025-06-28 06:32:05
test
详解装饰器(了解)
Python 装饰器(Decorator)是 Python 中一种强大的语法特性,它允许在不修改原函数或类代码的前提下,动态地扩展或修改其功能。装饰器的本质是一个 高阶函数,它接受一个函数或类作为参数,并返回一个新的函数或类,从而实现对原始对象的“包装”或“增强”。
一、装饰器的核心原理
1. 函数是一等对象
Python 中的函数是一等对象(First-Class Object),这意味着:
- 函数可以作为参数传递给其他函数。
- 函数可以作为其他函数的返回值。
- 函数可以被赋值给变量。
2. 闭包(Closure)
装饰器的实现依赖于 闭包。闭包是指在一个函数内部定义的函数,并且该内部函数可以访问外部函数的变量。
3. 高阶函数
装饰器本质上是一个高阶函数,它接收一个函数作为参数,并返回一个新的函数。
二、装饰器的基本语法
1. 简单装饰器
def my_decorator(func):
def wrapper():
print("函数执行前的操作")
func()
print("函数执行后的操作")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
输出:
函数执行前的操作
Hello!
函数执行后的操作
2. 语法糖 @ 的作用
@my_decorator等价于say_hello = my_decorator(say_hello)。- Python 会自动将
say_hello函数传递给my_decorator,并用返回的wrapper替换原函数。
三、装饰器的实现原理
装饰器的核心思想是通过 闭包函数 包裹原始函数,并在其前后添加额外逻辑。以下是一个通用装饰器的模板:
def decorator(func):
def wrapper(*args, **kwargs):
# 执行前的逻辑
result = func(*args, **kwargs)
# 执行后的逻辑
return result
return wrapper
示例:记录函数执行时间
import time
def get_time(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"函数 {func.__name__} 执行耗时: {end - start:.6f} 秒")
return result
return wrapper
@get_time
def slow_function(n):
sum(x for x in range(n))
slow_function(1000000)
四、装饰器的应用场景
1. 权限控制
def login_required(func):
def wrapper(*args, **kwargs):
user = "admin" # 模拟登录状态
if user == "admin":
return func(*args, **kwargs)
else:
print("请先登录!")
return wrapper
@login_required
def comment():
print("发表评论")
comment()
2. 缓存(Memoization)
def memoize(func):
cache = {}
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
@memoize
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(50)) # 快速计算斐波那契数
3. 日志记录
def log(func):
def wrapper(*args, **kwargs):
print(f"调用函数 {func.__name__},参数: {args}, {kwargs}")
result = func(*args, **kwargs)
print(f"函数 {func.__name__} 返回值: {result}")
return result
return wrapper
@log
def add(a, b):
return a + b
add(3, 5)
五、装饰器的高级用法
1. 带参数的装饰器
装饰器本身也可以接收参数,需要再嵌套一层函数:
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 greet(name):
print(f"Hello, {name}!")
greet("Alice")
2. 类装饰器
装饰器不仅可以是函数,还可以是类(需实现 __call__ 方法):
class CountCalls:
def __init__(self, func):
self.func = func
self.num_calls = 0
def __call__(self, *args, **kwargs):
self.num_calls += 1
print(f"函数已被调用 {self.num_calls} 次")
return self.func(*args, **kwargs)
@CountCalls
def example():
print("执行示例函数")
example()
example()
example()
3. 保留原函数的元信息
使用 functools.wraps 保留原函数的名称和文档字符串:
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("装饰器逻辑")
return func(*args, **kwargs)
return wrapper
@my_decorator
def original_function():
"""这是一个原函数"""
pass
print(original_function.__name__) # 输出: original_function
print(original_function.__doc__) # 输出: 这是一个原函数
六、装饰器的执行时机
- 装饰器定义时:装饰器函数在模块加载时立即执行。
- 装饰器调用时:装饰器返回的
wrapper函数在目标函数被调用时执行。
def my_decorator(func):
print("装饰器被定义时执行")
def wrapper():
print("装饰器逻辑执行")
func()
return wrapper
@my_decorator
def target():
print("目标函数")
print("装饰器定义完成")
target()
输出:
装饰器被定义时执行
装饰器定义完成
装饰器逻辑执行
目标函数
七、内置装饰器速查表
| 装饰器 | 用途说明 |
|---|---|
@property |
将方法伪装成属性访问(常用于只读属性)。 |
@classmethod |
定义类方法,第一个参数是类本身(cls)。 |
@staticmethod |
定义静态方法,无需 self 或 cls 参数。 |
@lru_cache |
缓存函数结果(基于最近最少使用策略)。 |
@dataclass |
自动生成数据类的 __init__、__repr__ 等方法。 |
@contextmanager |
使用 with 语句实现上下文管理器。 |
八、总结
装饰器是 Python 中非常强大的工具,它能够显著提升代码的复用性和可维护性。通过装饰器,你可以:
- 在不修改原始代码的情况下扩展功能。
- 实现统一的日志记录、权限控制、性能分析等逻辑。
- 提高代码的简洁性和可读性。
掌握装饰器后,你可以在实际开发中灵活应用它,比如构建 REST API 的路由、实现缓存机制、进行权限校验等。
浙公网安备 33010602011771号