Декоратор класса — это функция, принимающая класс в качестве аргумента и возвращающая либо модифицированный, либо совершенно новый класс. С их помощью можно динамически добавлять методы, изменять поведение существующих методов или даже возвращать подкласс, расширяющий функциональность оригинального класса.
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))
История
В е-commerce приложении хотели логировать методы класса, но случайно случайно вернули не тот объект из декоратора, и методы потеряли свойство класса, из-за чего перестали правильно наследоваться, сломав работу модели.
История
На проекте для автогенерации новых методов использовали декоратор-добавлятор, но забыли про super() при возврате подкласса. В результате нарушилась иерархия и MRO, приведя к неработающим вызовам базового класса в дочерних.
История
В data pipeline попытались обернуть классы несколькими декораторами (логер, трекер изменений), но из-за неверного порядка применения получили конфликт имен методов, что привело к багам в продакшене из-за "потерянных" методов.