装饰器是一种特殊类型的Python函数,它可以用来修改其他函数或方法的行为。当装饰器应用于一个类方法时,它可以在调用该方法之前或之后执行额外的逻辑,而不需要修改方法本身的代码。
装饰器本质上是一个接受函数作为参数并返回一个新函数的函数。在Python中,装饰器通常用于日志记录、访问控制、缓存、验证等场景。
以下是一个简单的装饰器示例,用于限制对类属性的访问:
def access_control(allowed_roles):
def decorator(func):
def wrapper(self, *args, **kwargs):
if self.role in allowed_roles:
return func(self, *args, **kwargs)
else:
raise PermissionError(f"User with role {self.role} is not allowed to access this method.")
return wrapper
return decorator
class MyClass:
def __init__(self, role):
self.role = role
self._sensitive_data = "This is sensitive data."
@access_control(allowed_roles=['admin'])
def get_sensitive_data(self):
return self._sensitive_data
# 使用示例
user1 = MyClass(role='admin')
print(user1.get_sensitive_data()) # 输出: This is sensitive data.
user2 = MyClass(role='guest')
try:
print(user2.get_sensitive_data())
except PermissionError as e:
print(e) # 输出: User with role guest is not allowed to access this method.
access_control
是一个装饰器工厂函数,它接受一个参数 allowed_roles
并返回一个实际的装饰器。@access_control(allowed_roles=['admin'])
应用于 get_sensitive_data
方法,确保只有角色为 'admin' 的用户才能访问该方法。wrapper
函数中,检查当前实例的 role
属性是否在允许的角色列表中。如果不在,则抛出 PermissionError
。装饰器可以是简单的函数,也可以是类(通过实现 __call__
方法)。它们可以接受参数,也可以不接受参数。
问题:装饰器导致方法签名改变,影响反射和文档生成工具。
解决方法:使用 functools.wraps
装饰器来保留原始函数的元数据。
from functools import wraps
def access_control(allowed_roles):
def decorator(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
if self.role in allowed_roles:
return func(self, *args, **kwargs)
else:
raise PermissionError(f"User with role {self.role} is not allowed to access this method.")
return wrapper
return decorator
通过这种方式,装饰器不会改变被装饰方法的名称、文档字符串等属性,从而避免了上述问题。
领取专属 10元无门槛券
手把手带您无忧上云