← Назад к вопросам
Что записывается через @ в Python?
2.3 Middle🔥 51 комментариев
#DevOps и инфраструктура
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
@ в Python: Декораторы
@ — это синтаксический сахар для декораторов (decorators). Декоратор — это функция, которая модифицирует поведение другой функции или класса, не изменяя её исходный код. Это мощный инструмент для добавления функциональности.
Базовая концепция
# ❌ Без декоратора — объемное и повторяющееся
def greet():
print("Starting greet...")
print("Hello, World!")
print("Finished greet.")
# ✅ С декоратором — чистый код
@log_execution
def greet():
print("Hello, World!")
# Оба варианта работают одинаково, но второй чище
Как работает @
# Это:
@decorator
def func():
pass
# Эквивалентно:
func = decorator(func)
# Декоратор принимает функцию и возвращает обёрнутую функцию
Простой пример: логирование
def log_execution(func):
"""Декоратор для логирования вызова функции"""
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with args={args}, kwargs={kwargs}")
result = func(*args, **kwargs) # Вызываем оригинальную функцию
print(f"{func.__name__} returned {result}")
return result
return wrapper
@log_execution
def add(a, b):
return a + b
# Использование
result = add(2, 3)
# Вывод:
# Calling add with args=(2, 3), kwargs={}
# add returned 5
# result = 5
Декоратор с параметрами
def repeat(times):
"""Декоратор с параметром: повторяет функцию N раз"""
def decorator(func):
def wrapper(*args, **kwargs):
results = []
for i in range(times):
result = func(*args, **kwargs)
results.append(result)
return results
return wrapper
return decorator
@repeat(times=3)
def greet():
return "Hello!"
result = greet()
print(result) # ['Hello!', 'Hello!', 'Hello!']
Практический пример: авторизация в веб-приложении
from functools import wraps
from flask import Flask, request
app = Flask(__name__)
def require_auth(func):
"""Декоратор для проверки авторизации"""
@wraps(func) # Сохраняет metadata оригинальной функции
def wrapper(*args, **kwargs):
token = request.headers.get('Authorization')
if not token:
return {"error": "No token"}, 401
# Проверяем токен
user = verify_token(token)
if not user:
return {"error": "Invalid token"}, 401
# Передаём user в функцию
return func(user=user, *args, **kwargs)
return wrapper
@app.route('/api/profile')
@require_auth
def get_profile(user):
return {"user_id": user.id, "name": user.name}
def verify_token(token):
# Логика проверки токена
if token == "valid-token":
return {"id": 1, "name": "John"}
return None
Множественные декораторы
# Декораторы применяются снизу вверх (bottom-to-top)
@log_execution
@check_permission
@require_auth
def delete_user(user_id):
# ...
pass
# Эквивалентно:
delete_user = log_execution(
check_permission(
require_auth(delete_user)
)
)
# Порядок выполнения:
# 1. require_auth проверяет авторизацию
# 2. check_permission проверяет права
# 3. log_execution логирует
Декоратор класса
def singleton(cls):
"""Декоратор для паттерна Singleton"""
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class DatabaseConnection:
def __init__(self, url):
self.url = url
# Всегда вернёт один инстанс
db1 = DatabaseConnection("postgresql://localhost")
db2 = DatabaseConnection("postgresql://localhost")
assert db1 is db2 # True — один объект!
Встроенные декораторы Python
# @property — превращает метод в свойство
class User:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def full_name(self):
return f"{self.first_name} {self.last_name}"
user = User("John", "Doe")
print(user.full_name) # John Doe (выглядит как свойство)
# @staticmethod — не получает self
class Math:
@staticmethod
def add(a, b):
return a + b
Math.add(2, 3) # 5
# @classmethod — получает cls вместо self
class MyClass:
count = 0
@classmethod
def increment(cls):
cls.count += 1
MyClass.increment() # Работает с классом, не инстансом
# @abstractmethod — абстрактный метод
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
Пример из реальной жизни: кеширование
from functools import lru_cache
import time
@lru_cache(maxsize=128)
def expensive_calculation(n):
"""Встроенный декоратор для кеширования результатов"""
time.sleep(1) # Имитируем долгую операцию
return n * n
start = time.time()
print(expensive_calculation(5)) # Медленно, ~1 сек
print(time.time() - start) # 1.0
start = time.time()
print(expensive_calculation(5)) # Быстро, из кеша
print(time.time() - start) # 0.0001
Декоратор для проверки типов
def type_check(**type_hints):
"""Проверяет типы аргументов функции"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for key, expected_type in type_hints.items():
if key in kwargs:
if not isinstance(kwargs[key], expected_type):
raise TypeError(
f"Argument {key} must be {expected_type}, "
f"got {type(kwargs[key])}"
)
return func(*args, **kwargs)
return wrapper
return decorator
@type_check(name=str, age=int)
def create_user(name, age):
return {"name": name, "age": age}
create_user(name="John", age=25) # OK
create_user(name="John", age="25") # TypeError!
Важные утилиты
from functools import wraps
# ВСЕГДА используй @wraps при создании декораторов
def my_decorator(func):
@wraps(func) # ← Важно!
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
# Почему важно:
@my_decorator
def my_function():
"""Это docstring"""
pass
print(my_function.__name__) # 'my_function' (не 'wrapper')
print(my_function.__doc__) # 'Это docstring' (сохранён)
Заключение
@ в Python — это синтаксис для декораторов, которые оборачивают функции и классы, добавляя функциональность. Декораторы используются везде: в фреймворках (Flask, Django), для кеширования, логирования, проверки прав доступа и многого другого. Это один из самых мощных инструментов Python.