<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Python декораторы: простое объяснение с примерами и кодом]]></title><description><![CDATA[<p dir="auto">Декораторы в Python — это мощный инструмент для расширения функций без изменения их кода. Они позволяют добавлять логику вроде логирования, кэширования или проверки доступа, делая код чище и повторно используемым.</p>
<p dir="auto">Зачем они нужны? Представь, что у тебя есть функция для вычисления, и ты хочешь каждый раз измерять её время или логировать вызовы. Вместо копипасты кода везде просто пишешь декоратор и вешаешь его одной строкой. Это решает проблему дублирования и упрощает поддержку.</p>
<h2>Что такое декоратор на самом деле</h2>
<p dir="auto">Декоратор — это функция, которая принимает другую функцию как аргумент, оборачивает её в новую логику и возвращает обновлённую версию. Всё происходит автоматически с помощью синтаксиса @имя_декоратора. Это как обёртка: внешний слой добавляет поведение, а внутри остаётся оригинальная функция.</p>
<p dir="auto">Рассмотрим базовый пример. Допустим, у нас есть простая функция say_hi, которая возвращает строку “всем привет”. Декоратор сделает буквы заглавными, не трогая код функции. Оборачиваем функцию во внутреннюю wrapper, выполняем нужную логику до и после вызова оригинала — и готово. Такой подход работает для любых функций, даже с параметрами.</p>
<p dir="auto">Вот как выглядит структура:</p>
<ul>
<li>Декоратор принимает func.</li>
<li>Внутри создаёт wrapper, которая вызывает func с аргументами.</li>
<li>Wrapper возвращает результат func плюс добавленная логика.</li>
</ul>
<pre><code class="language-python">def uppercase_decorator(func):
    def wrapper():
        result = func()
        return result.upper()
    return wrapper

@uppercase_decorator
def say_hi():
    return "всем привет"

print(say_hi())  # ВСЕМ ПРИВЕТ
</code></pre>
<p dir="auto"><strong>Ключевой момент</strong>: *wrapper должна принимать *args и *<em>kwargs, чтобы декоратор работал с любыми функциями.</em></p>
<h2>Простые примеры декораторов в действии</h2>
<p dir="auto">Начнём с логирования. Представь функцию, которая печатает имя. Декоратор перед вызовом выведет “Функция вызвана”. Это полезно для отладки: видишь стек вызовов без if-ов повсюду. Аналогично можно добавить timestamp или уровень логирования.</p>
<p dir="auto">Другой пример — замер времени. Функция вычисляет сумму списка, а декоратор покажет, сколько прошло миллисекунд. Импортируешь time, фиксируешь start и end в wrapper — и вуаля. Идеально для оптимизации кода.</p>
<p dir="auto">Переходим к деталям. Вот типичные случаи:</p>
<ul>
<li><strong>Логирование</strong>: print(f"Вызвана {func.<strong>name</strong>}")</li>
<li><strong>Время выполнения</strong>: time.perf_counter() до и после</li>
<li><strong>Проверка аргументов</strong>: raise ValueError, если не ок</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Пример декоратора</th>
<th>Что добавляет</th>
<th>Когда использовать</th>
</tr>
</thead>
<tbody>
<tr>
<td>Логирование</td>
<td>Сообщение о вызове</td>
<td>Отладка, мониторинг</td>
</tr>
<tr>
<td>Тайминг</td>
<td>Время в мс</td>
<td>Профилирование</td>
</tr>
<tr>
<td>Кэширование</td>
<td>Сохранение результата</td>
<td>Дорогие вычисления</td>
</tr>
</tbody>
</table>
<p dir="auto">Эти примеры показывают, как декораторы упрощают жизнь. <em>Не забывай возвращать результат func, иначе функция ничего не отдаст.</em></p>
<h2>Декораторы с параметрами и несколько штук сразу</h2>
<p dir="auto">Обычный декоратор не принимает аргументы сам по себе. Чтобы добавить параметры, создай фабрику: внешняя функция принимает настройки, внутри — настоящий декоратор с wrapper. Например, декоратор повторений: @retry(times=3) — попробует функцию 3 раза при ошибке.</p>
<p dir="auto">С несколькими декораторами порядок важен. Они применяются снизу вверх: первый ближе к функции оборачивает её, следующий — результат предыдущего. Если @log над @time, то сначала time, потом log. Это накапливает эффекты: время + лог + валидация.</p>
<p dir="auto">Структура декоратора с параметрами:</p>
<ol>
<li>Внешняя функция repeat(n):</li>
<li>Возвращает decorator(func)</li>
<li>Decorator возвращает wrapper с циклом на n попыток</li>
<li>Wrapper ловит исключения и retry</li>
</ol>
<pre><code class="language-python">def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                try:
                    return func(*args, **kwargs)
                except:
                    pass
            raise
        return wrapper
    return decorator

@repeat(3)
def risky_func():
    # может упасть
    pass
</code></pre>
<p dir="auto"><strong>Важно</strong>: сохраняй метаданные func с functools.wraps(func) — имя, докстринг останутся правильными.</p>
<h2>Декораторы на классах и продвинутые фичи</h2>
<p dir="auto">Не только функции: классы с <strong>init</strong> и <strong>call</strong> тоже декораторы. В <strong>init</strong> сохраняешь func, в <strong>call</strong> — выполняешь логику. Полезно для состояний, как счётчик вызовов или кэш в атрибуте.</p>
<p dir="auto">Применение: мемоизация. Декоратор хранит результаты в словаре {args: result}. При повторном вызове с теми же аргументами — берёт из кэша. Идеально для рекурсии Фибоначчи или API-запросов.</p>
<p dir="auto">Продвинутые примеры:</p>
<ul>
<li><strong>Мемоизация</strong>: @lru_cache из functools</li>
<li><strong>Состояние в классе</strong>: self.count +=1</li>
<li><strong>Для методов</strong>: self-aware wrapper</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Тип декоратора</th>
<th>Преимущества</th>
<th>Ограничения</th>
</tr>
</thead>
<tbody>
<tr>
<td>Функция</td>
<td>Просто</td>
<td>Нет состояния</td>
</tr>
<tr>
<td>Класс</td>
<td>Состояние</td>
<td>Словеснее</td>
</tr>
<tr>
<td>functools</td>
<td>Готовые</td>
<td>Меньше контроля</td>
</tr>
</tbody>
</table>
<p dir="auto"><em>Классовые декораторы хороши, когда нужна память между вызовами.</em></p>
<h2>Когда декораторы меняют правила игры</h2>
<p dir="auto">Декораторы — это не просто сахар: они принцип SOLID в действии. Модифицируешь поведение без изменения класса или функции, делая код модульным. В веб-фреймворках вроде Flask они проверяют роли, в тестах — мокнут зависимости.</p>
<p dir="auto">Осталось место для размышлений: как комбинировать с async/await или генераторами? Или создать декоратор для валидации схем с pydantic. Подумай над своими проектами — наверняка найдётся, где упростить логику.</p>
<p dir="auto">Это базовый набор, чтобы стартовать уверенно. Дальше экспериментируй с реальными задачами.</p>
]]></description><link>https://forum.exlends.ru/topic/617/python-dekoratory-prostoe-obuyasnenie-s-primerami-i-kodom</link><generator>RSS for Node</generator><lastBuildDate>Sat, 17 Oct 2026 03:12:24 GMT</lastBuildDate><atom:link href="https://forum.exlends.ru/topic/617.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 20 Feb 2026 16:45:00 GMT</pubDate><ttl>60</ttl></channel></rss>