面试题答案
一键面试避免重复代码
- 使用辅助函数:将通用逻辑封装到辅助函数中,不同装饰器可复用。
def log_message(message):
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
logger.info(message)
def log_decorator(cls):
def wrapper(*args, **kwargs):
log_message(f"Calling {cls.__name__}")
return cls(*args, **kwargs)
return wrapper
def permission_decorator(cls):
def wrapper(*args, **kwargs):
log_message(f"Checking permissions for {cls.__name__}")
# 实际权限验证逻辑
return cls(*args, **kwargs)
return wrapper
@log_decorator
@permission_decorator
class MyClass:
def __init__(self):
pass
my_obj = MyClass()
- 继承和组合:通过继承或组合方式复用已有的装饰器逻辑。
class BaseDecorator:
def __init__(self, func):
self.func = func
class LogDecorator(BaseDecorator):
def __call__(self, *args, **kwargs):
log_message(f"Calling {self.func.__name__}")
return self.func(*args, **kwargs)
class PermissionDecorator(BaseDecorator):
def __call__(self, *args, **kwargs):
log_message(f"Checking permissions for {self.func.__name__}")
# 实际权限验证逻辑
return self.func(*args, **kwargs)
def my_function():
pass
logged_function = LogDecorator(my_function)
permitted_function = PermissionDecorator(logged_function)
处理装饰器之间的依赖关系
- 确定顺序:明确装饰器执行顺序,如先权限验证后日志记录。
在上述代码示例中,
@log_decorator
和@permission_decorator
的顺序决定了先检查权限再记录日志。如果顺序颠倒,就会先记录日志再检查权限。 - 传递数据:如果装饰器间需要传递数据,可以通过闭包或类属性实现。
def data_passing_decorator(func):
data = {}
def wrapper(*args, **kwargs):
data['result'] = func(*args, **kwargs)
return data
return wrapper
def use_data_decorator(func):
def wrapper(data):
result = func(data)
print(f"Using data from previous decorator: {data['result']}")
return result
return wrapper
@use_data_decorator
@data_passing_decorator
def example_function():
return 42
result = example_function()
性能优化
- 缓存结果:对于一些重复计算的结果,比如权限验证的结果,可进行缓存。
permission_cache = {}
def optimized_permission_decorator(cls):
def wrapper(*args, **kwargs):
if cls.__name__ not in permission_cache:
# 实际权限验证逻辑
permission_cache[cls.__name__] = True
if permission_cache[cls.__name__]:
return cls(*args, **kwargs)
else:
raise PermissionError
return wrapper
- 减少函数调用开销:尽量减少装饰器内部不必要的函数调用。在复杂装饰器逻辑中,将一些计算逻辑提前到装饰器定义时执行,而不是在每次被装饰函数调用时执行。
通过上述方法,可以在类装饰器处理日志记录、权限验证等场景下,提高代码的可维护性和性能。