← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Python Decorators

python Python 2.4+ Intermediate

Also Known As

Python decorator @decorator syntax function decorator

TL;DR

Functions that wrap other functions to add behaviour — @cache, @dataclass, @property — applied at definition time with the @ syntax.

Explanation

A decorator is a callable that takes a function and returns a modified version. @functools.wraps preserves the original function's name and docstring. Built-in decorators: @property (computed attribute), @staticmethod (no self/cls), @classmethod (receives cls), @functools.cache (memoisation), @functools.lru_cache(maxsize=128). Decorator factories take arguments: @lru_cache(maxsize=256). Class decorators: @dataclass generates __init__, __repr__, __eq__ from class annotations — Python's equivalent of PHP 8.1 readonly classes. Stacking: @app.route('/') @login_required applies inside-out. PHP's equivalent is attribute-based annotations (#[Route]) or middleware patterns — Python decorators are more powerful because they execute arbitrary code, not just metadata.

Diagram

flowchart LR
    subgraph Decorator_Mechanics
        ORIG[def my_func]
        WRAP[def decorator wraps func]
        APPLIED[my_func = decorator my_func]
        ORIG --> WRAP --> APPLIED
    end
    subgraph Common_Uses
        TIMING[measure_time decorator<br/>log execution duration]
        CACHE2[functools.lru_cache<br/>memoize results]
        AUTH2[require_auth decorator<br/>check before running]
        RETRY2[retry decorator<br/>retry on exception]
    end
    subgraph Syntax
        AT[at symbol decorator<br/>above function definition<br/>syntactic sugar]
    end
style APPLIED fill:#238636,color:#fff
style CACHE2 fill:#1f6feb,color:#fff
style AUTH2 fill:#f85149,color:#fff

Common Misconception

Python decorators modify the original function in place. Decorators replace the original function with a wrapper — without functools.wraps, the decorated function loses its __name__, __doc__, and signature. Always use @functools.wraps(func) inside decorators to preserve metadata.

Why It Matters

Python decorators wrap functions or classes to add behaviour — used for caching, logging, auth, retry, and timing without modifying the function's core logic.

Common Mistakes

  • Not using functools.wraps — the decorated function loses its __name__ and __doc__.
  • Decorators that do not handle the wrapped function's arguments correctly — use *args, **kwargs.
  • Stateful decorators without thread safety — mutable state in a decorator is shared across calls.
  • Stacking too many decorators — execution order is bottom-up for application and top-down for stacking.

Code Examples

✗ Vulnerable
# Decorator without functools.wraps — loses metadata:
def log_call(func):
    def wrapper(*args, **kwargs):
        print(f'Calling {func.__name__}')
        return func(*args, **kwargs)
    return wrapper  # wrapper.__name__ is 'wrapper', not 'original'

# Fixed:
import functools
def log_call(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs): ...
    return wrapper
✓ Fixed
import functools

def retry(times=3):
    def decorator(fn):
        @functools.wraps(fn)
        def wrapper(*args, **kwargs):
            for i in range(times):
                try: return fn(*args, **kwargs)
                except Exception:
                    if i == times - 1: raise
        return wrapper
    return decorator

@retry(times=5)
def fetch_data(): ...

Added 15 Mar 2026
Edited 22 Mar 2026
Views 27
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
3 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T
No pings yet today
No pings yesterday
Perplexity 7 Amazonbot 6 Google 2 Unknown AI 2 Ahrefs 2
crawler 19
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Medium
⚡ Quick Fix
Always use functools.wraps(func) inside your decorator to preserve the wrapped function's __name__, __doc__, and type hints
📦 Applies To
python 2.4 web cli
🔗 Prerequisites
🔍 Detection Hints
Decorator missing @functools.wraps(func) losing wrapped function metadata; repeated cross-cutting concerns not extracted as decorators
Auto-detectable: ✓ Yes pylint ruff mypy
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: Function Tests: Update

✓ schema.org compliant