类装饰器是一个接受类作为参数并返回修改后的或全新类的函数。通过它们,可以动态添加方法,修改现有方法的行为,甚至返回一个子类以扩展原始类的功能。
def add_repr(cls): def __repr__(self): return f'<{cls.__name__}: {self.__dict__}>' cls.__repr__ = __repr__ return cls @add_repr class Point: def __init__(self, x, y): self.x = x self.y = y p = Point(3, 4) print(p) # <Point: {'x': 3, 'y': 4}>
add_repr 动态为所有应用它的类添加了 __repr__ 方法。*args 和 **kwargs,则可能会出现错误。如果依次应用两个类装饰器会发生什么?它们的应用顺序总是明显的吗?
装饰器的应用是“自下而上”的:首先应用直接在类声明上方的装饰器,然后是上方的下一个,以此类推。顺序非常重要,因为第一个装饰器的结果会传递给第二个,依此类推。
@dec1 @dec2 class Test: ... # 等同于: # Test = dec1(dec2(Test))
故事
在电子商务应用中,想要记录类的方法,但意外地从装饰器返回了错误的对象,导致方法失去了类特性,从而无法正确继承,破坏了模型的工作。
故事
在项目中,为自动生成新方法使用了一个添加装饰器,但在返回子类时忘记了 super()。结果破坏了层次结构和 MRO,导致子类中的基础类调用无法工作。
故事
在数据管道中尝试用多个装饰器(记录器、变更跟踪器)包装类,但由于应用顺序错误导致了方法名称冲突,导致生产环境中的错误,因为“丢失”的方法。