← Назад к вопросам

Что такое декораторы в Python?

2.2 Middle🔥 171 комментариев
#Python#Фреймворки тестирования

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое декораторы в Python

Определение

Декоратор — это функция, которая принимает другую функцию или класс, модифицирует его поведение и возвращает обновленную версию. Декораторы используют сигнатуру @decorator_name.

Базовый пример

def my_decorator(func):
    def wrapper():
        print("Перед вызовом функции")
        func()
        print("После вызова функции")
    return wrapper

@my_decorator
def hello():
    print("Hello, World!")

hello()
# Вывод:
# Перед вызовом функции
# Hello, World!
# После вызова функции

Декораторы с параметрами

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Функция {func.__name__} вызвана")
        result = func(*args, **kwargs)
        print(f"Результат: {result}")
        return result
    return wrapper

@my_decorator
def add(a, b):
    return a + b

add(3, 5)
# Вывод:
# Функция add вызвана
# Результат: 8

Декораторы в тестировании

import pytest
from unittest.mock import patch

# Пример 1: @pytest.fixture
@pytest.fixture
def db():
    database = create_db()
    yield database
    database.close()

def test_user_creation(db):
    user = db.create_user("John")
    assert user.name == "John"

# Пример 2: @pytest.mark.parametrize
@pytest.mark.parametrize("input,expected", [
    (2, 3, 5),
    (-1, 1, 0),
])
def test_add(a, b, expected):
    assert add(a, b) == expected

# Пример 3: @patch
@patch('requests.get')
def test_api_call(mock_get):
    mock_get.return_value.status_code = 200
    response = requests.get('https://api.example.com')
    assert response.status_code == 200

Декораторы для повторных попыток

import time
from functools import wraps

def retry(max_attempts=3, delay=1):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_attempts - 1:
                        raise
                    time.sleep(delay)
        return wrapper
    return decorator

@retry(max_attempts=3, delay=2)
def unstable_request():
    response = requests.get('https://api.example.com')
    return response

Встроенные декораторы pytest

# @pytest.mark.skip — пропустить тест
@pytest.mark.skip(reason="Пока не реализовано")
def test_future_feature():
    pass

# @pytest.mark.xfail — ожидаемый отказ
@pytest.mark.xfail(reason="Известная ошибка")
def test_known_bug():
    assert False

# @pytest.mark.slow — отметить медленный тест
@pytest.mark.slow
def test_database_operation():
    pass

Декораторы с состоянием

from functools import wraps

def measure_time(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        elapsed = time.time() - start
        print(f"Функция выполнена за {elapsed:.2f} секунд")
        return result
    return wrapper

@measure_time
def slow_function():
    time.sleep(2)
    return "Done"

Преимущества декораторов

  • Разделение ответственности (DRY)
  • Переиспользование кода
  • Читаемость
  • Модульность

Декораторы — это мощный инструмент для организации и улучшения тестов в pytest.