Към основното съдържание
Междинен Python2026-07-29 · 10 мин четене

Обяснени декоратори на Python: От @property до повторна логика за 15 минути (2026)

Декораторите са характеристиката, която разделя „познава Python“ от „чете Python свободно“. Изглеждат магически, но са механични: @decorator на функция е точно f = decorator(f). Това е. Всичко останало в този урок е една линия, приложена в различни форми.

Теорията на един ред

Когато пишете:

▶ PYTHONeditable · runs in your browser

Python го трансформира в:

▶ PYTHONeditable · runs in your browser

Това е цялата механика. @decorator_name над def изпълнява def_name = decorator_name(def_name) след дефиницията. Ако усвоите това, декораторите спират да бъдат мистериозни завинаги.

Писане на вашия първи декоратор (60 секунди)

Декораторът е всеки извикваем, който приема функция и връща функция. Типична форма:

▶ PYTHONeditable · runs in your browser

*args, **kwargs в обвивката е защитен модел — той позволява на декоратора да работи върху всяка функция, независимо от подписа. Пропуснете го и ще получите „TypeError: wrapper() приема 0 позиционни аргумента, но са дадени 2“ в момента, в който някой украси функция с параметри.

Поправката на @functools.wraps

Един фин бъг: след декориране, add.__name__ е "wrapper", а не "add". Документните низове и подсказките за тип също изчезват. Корекцията е едно импортиране:

▶ PYTHONeditable · runs in your browser

Правило: всеки декоратор, който пишете, трябва да използва `@functools.wraps(fn)`. Той струва един ред и предотвратява цяла категория болка при отстраняване на грешки (самоанализ, pytest приспособления, logging формати, pickle — всички прекъсват безшумно без него).

Четирите декоратора, които ще видите във всяка кодова база

1. @property — изчислени атрибути

▶ PYTHONeditable · runs in your browser

@property прави метод извикан сякаш като атрибут. Перфектен за извлечени стойности само за четене. Има и @area.setter за пътя за запис, но 90% от използванията на @property са само за четене.

2. @staticmethod и @classmethod

▶ PYTHONeditable · runs in your browser

@classmethod получава cls (самия клас) и се използва за алтернативни конструктори. @staticmethod не получава нищо специално и е обикновена функция, която просто живее в пространството на имената на класа.

3. @functools.cache — мемоизация

▶ PYTHONeditable · runs in your browser

Един от най-мощните декоратори на stdlib. Автоматично запаметява функцията въз основа на нейните аргументи. Изисква всички аргументи да могат да се хешират (без списъци / dicts като аргументи — използвайте кортежи).

4. @dataclasses.dataclass — елиминиране на шаблон

▶ PYTHONeditable · runs in your browser

@dataclass чете анотациите за тип на ниво клас и автоматично генерира __init__, __repr__, __eq__ и (с frozen=True) __hash__. Това е най-голямото подобрение на качеството на живот в Python 3.7+.

Писане на декоратор @retry (пример от реалния свят)

Декоратор, който опитва отново функция при повреда с експоненциално забавяне:

▶ PYTHONeditable · runs in your browser

Обърнете внимание на трите вложени функции: retry приема конфигурационните аргументи и връща decorator; decorator приема функцията и връща wrapper; wrapper изпълнява цикъла за повторен опит. Този трислоен модел е това, което всеки декоратор-с-аргументи изглежда - запомнете формата, а не конкретния пример.

Базирани на клас декоратори (рядко срещани, но полезни)

Декоратор е всеки, който може да бъде призован. Класове с __call__ също работят:

▶ PYTHONeditable · runs in your browser

Използвайте, когато декораторът трябва да задържи състояние, което надживява едно извикване (брояч, кеш, кофа за ограничаване на скоростта).

Често срещани клопки

1. Забравяне на `@functools.wraps` — интроспекцията прекъсва безшумно.

2. Променливи аргументи по подразбиране в самия декоратор — класическият def wrapper(x, cache=[]) бъгове и тук.

3. Декориране на методи без приемане на `self` — не забравяйте, че self е просто позиционен аргумент; *args, **kwargs го хваща добре.

4. Подреждането има значение при подреждане: @a\n@b\ndef f() е f = a(b(f)). Четете стекове отдолу нагоре.

Практикувайте

Напишете декоратор „@timing“, който отпечатва колко време отнема изпълнението на обвитата функция, след което го приложете към функция, която изчислява „sum(range(10_000_000))“. Целият декоратор е 8 реда с functools.wraps + time.perf_counter.


След като разберете, че @x е f = x(f), декораторите стават една от най-продуктивните функции на Python. Те са навсякъде в реални кодови бази: Flask/FastAPI маршрути (@app.route), pytest fixtures (@pytest.fixture), Django изгледи (@login_required), Pydantic валидатори (@field_validator). Научаването да ги пишете сами отключва способността да четете всеки един от тях.

Следваща стъпка: 10 практически урока по декориране — изградете @retry, @memoise, @rate_limit и @requires_auth от нулата с истински Python, работещ във вашия браузър.

Готови ли сте да опитате?

15 безплатни уроци след безплатна регистрация — без карта. Изпробвайте платформата и след това решете.

Започнете безплатно →

Or unlock every lesson

Pro — $12/mo, unlimited AI, cancel any time. Refund within 14 days worldwide.

See Pro plans →

Get one Python lesson + one career idea every Friday

No spam, no "buy our course now". Three bullets, every Friday. Unsubscribe with one click.