Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Какие знаешь встроенные декораторы Python?
Декораторы — мощный инструмент для модификации функций и классов. Вот основные встроенные декораторы, которые использую постоянно.
1. @property
Превращает метод в свойство (атрибут).
class DataSet:
def __init__(self, size):
self._size = size
@property
def size(self):
return self._size
@size.setter
def size(self, value):
if value < 0:
raise ValueError("Size must be positive")
self._size = value
ds = DataSet(1000)
print(ds.size) # Выглядит как атрибут
ds.size = 5000 # Валидация при присвоении
2. @staticmethod
Метод, который не требует доступа к self или cls.
class Math:
@staticmethod
def add(a, b):
return a + b
result = Math.add(5, 3) # 8
3. @classmethod
Метод получает доступ к cls (сам класс).
class Model:
instances_count = 0
def __init__(self, name):
self.name = name
Model.instances_count += 1
@classmethod
def get_count(cls):
return cls.instances_count
@classmethod
def from_dict(cls, data):
return cls(data['name'])
m1 = Model("M1")
print(Model.get_count()) # 1
4. @abstractmethod (из abc)
Определяет интерфейс для подклассов.
from abc import ABC, abstractmethod
class Estimator(ABC):
@abstractmethod
def fit(self, X, y):
pass
@abstractmethod
def predict(self, X):
pass
class MyModel(Estimator):
def fit(self, X, y):
pass
def predict(self, X):
pass
5. @lru_cache (из functools)
Кэширование результатов функции.
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
result = fibonacci(35) # Быстро благодаря кэшу
print(fibonacci.cache_info()) # Смотреть статистику
fibonacci.cache_clear() # Очистить кэш
6. @functools.wraps
Сохраняет метаданные оригинальной функции.
from functools import wraps
def my_decorator(func):
@wraps(func) # Копирует __name__, __doc__
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
@my_decorator
def add(a, b):
"Adds two numbers"
return a + b
print(add.__name__) # 'add' (не 'wrapper'!)
print(add.__doc__) # 'Adds two numbers'
7. @singledispatch (из functools)
Перегрузка функций в зависимости от типа аргумента.
from functools import singledispatch
@singledispatch
def process(arg):
raise NotImplementedError(f"Cannot process {type(arg)}")
@process.register(int)
def _(arg):
return arg * 2
@process.register(str)
def _(arg):
return arg.upper()
@process.register(list)
def _(arg):
return len(arg)
print(process(5)) # 10
print(process("hello")) # HELLO
print(process([1, 2])) # 2
8. Custom декоратор для ML
import time
from functools import wraps
def timing_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
print(f"{func.__name__}: {elapsed:.3f}s")
return result
return wrapper
@timing_decorator
def train_model(X, y):
from sklearn.ensemble import GradientBoostingClassifier
model = GradientBoostingClassifier(n_estimators=1000)
model.fit(X, y)
return model
Чек-лист при использовании декораторов
- @wraps при создании собственных декораторов
- @property для getter/setter логики
- @classmethod для factory methods
- @staticmethod для утилит
- @abstractmethod для определения интерфейсов
- @lru_cache только для pure functions (без побочных эффектов)
- Не перегружай декораторами — код должен быть читаемым
Порядок применения декораторов
@decorator1 # Применяется вторым
@decorator2 # Применяется первым
def func():
pass
# Эквивалент: func = decorator1(decorator2(func))
# Выполнение: decorator2 -> func -> decorator1