装饰器是Python中一个很有用的特性,它能够在不改变原有代码的情况下,给函数或类添加新的功能。这个功能让代码更加灵活,也更容易维护。
装饰器本质上是一个函数,它接受另一个函数作为参数,然后返回一个新的函数。使用装饰器可以在不修改原函数代码的情况下,为函数添加额外的功能。
在Python中,我们使用@符号来应用装饰器。Python本身也提供了一些内置的装饰器,比如@staticmethod和@classmethod。
装饰器在实际开发中有很多用途:
记录日志:记录函数的调用信息、参数和返回值
性能测试:测量函数的执行时间
权限检查:控制对某些函数的访问权限
结果缓存:存储函数计算结果,提高运行速度
错误重试:在函数失败时自动重试
我们先来看一个基本的装饰器结构:
def decorator_function(original_function):
def wrapper(*args, **kwargs):
# 在调用原函数前执行的代码
print("函数调用开始")
result = original_function(*args, **kwargs)
# 在调用原函数后执行的代码
print("函数调用结束")
return result
return wrapper
# 使用装饰器
@decorator_function
def target_function(arg1, arg2):
print(f"执行函数,参数:{arg1}, {arg2}")
# 测试
target_function("hello", "world")运行结果:
函数调用开始
执行函数,参数:hello, world
函数调用结束当我们使用@decorator_function时,实际上相当于执行了:
def target_function(arg1, arg2):
print(f"执行函数,参数:{arg1}, {arg2}")
target_function = decorator_function(target_function)原来的target_function被替换成了decorator_function(target_function)返回的wrapper函数。
import time
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"函数 {func.__name__} 执行耗时:{end_time - start_time:.4f}秒")
return result
return wrapper
@timer_decorator
def slow_function():
time.sleep(1)
print("函数执行完毕")
slow_function()如果原函数需要参数,装饰器需要这样写:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("准备执行函数")
result = func(*args, **kwargs)
print("函数执行完成")
return result
return wrapper
@my_decorator
def greet(name, age):
print(f"你好,{name},今年{age}岁")
greet("小明", 20)有时候我们需要让装饰器本身也能接受参数:
def repeat(num_times):
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(num_times):
print(f"第{i+1}次执行:")
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def say_hello():
print("Hello!")
say_hello()运行结果:
第1次执行:
Hello!
第2次执行:
Hello!
第3次执行:
Hello!这个例子中,repeat是一个装饰器工厂函数,它返回真正的装饰器。
除了函数装饰器,Python还支持类装饰器。类装饰器可以修改类的行为。
def add_method(cls):
def new_method(self):
return "这是新增的方法"
cls.new_method = new_method
return cls
@add_method
class MyClass:
def original_method(self):
return "这是原始方法"
obj = MyClass()
print(obj.original_method()) # 这是原始方法
print(obj.new_method()) # 这是新增的方法class SingletonDecorator:
def __init__(self, cls):
self.cls = cls
self.instance = None
def __call__(self, *args, **kwargs):
if self.instance is None:
self.instance = self.cls(*args, **kwargs)
return self.instance
@SingletonDecorator
class Database:
def __init__(self):
print("数据库连接已创建")
# 测试
db1 = Database()
db2 = Database()
print(db1 is db2) # 输出:TruePython提供了几个有用的内置装饰器:
静态方法,不需要访问类或实例的数据:
class MathUtils:
@staticmethod
def add(x, y):
return x + y
# 直接通过类调用,不需要创建实例
result = MathUtils.add(5, 3)
print(result) # 输出:8类方法,第一个参数是类本身:
class Person:
count = 0
def __init__(self, name):
self.name = name
Person.count += 1
@classmethod
def get_count(cls):
return cls.count
person1 = Person("小明")
person2 = Person("小红")
print(Person.get_count()) # 输出:2将方法转换为属性:
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("半径必须大于0")
self._radius = value
@property
def area(self):
return 3.14159 * self._radius ** 2
circle = Circle(5)
print(circle.area) # 输出:78.53975
circle.radius = 10
print(circle.area) # 输出:314.159可以同时使用多个装饰器,它们会从下往上依次执行:
def decorator1(func):
def wrapper():
print("装饰器1 - 前")
func()
print("装饰器1 - 后")
return wrapper
def decorator2(func):
def wrapper():
print("装饰器2 - 前")
func()
print("装饰器2 - 后")
return wrapper
@decorator1
@decorator2
def my_function():
print("原始函数")
my_function()运行结果:
装饰器1 - 前
装饰器2 - 前
原始函数
装饰器2 - 后
装饰器1 - 后def cache_decorator(func):
cache = {}
def wrapper(*args):
if args in cache:
print("从缓存中获取结果")
return cache[args]
result = func(*args)
cache[args] = result
print("计算结果并缓存")
return result
return wrapper
@cache_decorator
def expensive_calculation(x):
return x * x
print(expensive_calculation(5)) # 计算结果并缓存 \n 25
print(expensive_calculation(5)) # 从缓存中获取结果 \n 25def login_required(func):
def wrapper(user, *args, **kwargs):
if not user.get('is_login', False):
print("请先登录")
return None
return func(user, *args, **kwargs)
return wrapper
@login_required
def view_profile(user):
print(f"显示用户资料:{user['name']}")
# 测试
user1 = {'name': '小明', 'is_login': True}
user2 = {'name': '小红', 'is_login': False}
view_profile(user1) # 显示用户资料:小明
view_profile(user2) # 请先登录import time
def retry(max_attempts=3, delay=1):
def decorator(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 e
print(f"第{attempt + 1}次尝试失败,{delay}秒后重试")
time.sleep(delay)
return None
return wrapper
return decorator
@retry(max_attempts=3, delay=2)
def unstable_operation():
import random
if random.random() < 0.7:
raise Exception("操作失败")
return "操作成功"
result = unstable_operation()
print(result)保留原函数信息:使用functools.wraps保留原函数的元信息
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("装饰器功能")
return func(*args, **kwargs)
return wrapper调试装饰器:装饰器可能会让错误信息更难理解,要注意调试
性能考虑:装饰器会增加函数调用开销,在性能敏感的场景要谨慎使用
装饰器是Python中强大的功能,它让我们能够:
在不修改原代码的情况下添加功能
保持代码的整洁和可读性
实现通用的功能,如日志、缓存、权限检查等
通过组合不同的装饰器来构建复杂的功能
掌握装饰器的使用,能够让你的Python代码更加专业和强大。从简单的函数装饰器到复杂的类装饰器,这个功能在实际开发中有着广泛的应用。
记住,装饰器虽然强大,但也不要过度使用。在合适的场景使用合适的装饰器,才能让代码既强大又易于维护。
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!