装饰器模式是一种结构型设计模式,它允许你在不修改原有对象的基础上,动态地给一个对象添加新的功能。在Python中,装饰器是一种非常常见的实现方式,通常用于日志记录、访问控制、性能测试、事务处理等场景。
装饰器本质上是一个接受函数或方法作为参数,并返回一个增强版函数或方法的高阶函数。在Python中,装饰器通常使用@decorator_name
语法糖来应用。
类装饰器是装饰器的一种形式,它接受一个类作为参数,并返回一个新的类。类装饰器可以在不修改原类的情况下,增加新的功能或修改类的行为。
下面是一个简单的类装饰器的示例,用于记录方法的调用日志:
def log_method_calls(cls):
class Wrapper:
def __init__(self, *args, **kwargs):
self.wrapped = cls(*args, **kwargs)
def __getattr__(self, name):
attr = getattr(self.wrapped, name)
if callable(attr):
def logged_method(*args, **kwargs):
print(f"Calling {name} with args {args} and kwargs {kwargs}")
result = attr(*args, **kwargs)
print(f"{name} returned {result}")
return result
return logged_method
return attr
return Wrapper
@log_method_calls
class MyClass:
def my_method(self, x):
return x * 2
# 使用装饰后的类
obj = MyClass()
print(obj.my_method(3)) # 输出: Calling my_method with args (3,) and kwargs {}
# my_method returned 6
# 6
装饰器可能会改变原始方法的签名,导致类型检查工具(如mypy)报错。
解决方法:使用functools.wraps
来保留原始方法的元数据。
import functools
def log_method_calls(cls):
class Wrapper:
def __init__(self, *args, **kwargs):
self.wrapped = cls(*args, **kwargs)
def __getattr__(self, name):
attr = getattr(self.wrapped, name)
if callable(attr):
@functools.wraps(attr)
def logged_method(*args, **kwargs):
print(f"Calling {name} with args {args} and kwargs {kwargs}")
result = attr(*args, **kwargs)
print(f"{name} returned {result}")
return result
return logged_method
return attr
return Wrapper
装饰器中的额外逻辑可能会影响程序的性能。
解决方法:优化装饰器中的逻辑,或者在不需要时移除装饰器。
通过以上方法,可以有效地使用装饰器类来修饰方法,同时避免常见的问题。
领取专属 10元无门槛券
手把手带您无忧上云