Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Python’s @decorator syntax transforms a function or class as its definition executes, then binds the name to the transformed result. The syntax is not inherently deceptive or unsafe—but a decorator can make code feel opaque when its effects are unclear, especially when several are stacked.

What @decorator means

For a function, Python creates the function object, applies the decorator to it, and binds the function’s name to whatever the decorator returns. In the simple case, @decorator is equivalent to writing func = decorator(func) after defining func. Decoration happens when execution reaches the definition, not each time the function is later called. See the Python language reference.

@decorator
def func():
    ...

That is conceptually equivalent to:

def func():
    ...
func = decorator(func)

The reassignment makes one important detail explicit: after decoration, the name refers to the returned object. A decorator might return the original function, a wrapped function, or another object that serves the same role.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How stacked decorators are applied

When decorators are stacked, Python applies them from the one nearest the def outward. In other words, the visual order runs top to bottom, but the transformations compose bottom to top:

@dec2
@dec1
def func():
    ...

This is equivalent to func = dec2(dec1(func)). dec1 receives the original function first; dec2 receives the result of that application. The order matters because changing it can change the final object. This composition rule is specified in PEP 318.

Can a decorator take arguments?

Yes. The expression after @ can call a factory that returns a decorator. For example, @decomaker(arg) means the result of calling decomaker(arg) is applied to the newly defined function. This adds a layer to keep track of: first the factory call produces a decorator, then that decorator receives the function. PEP 318 describes this form and notes that decorator expressions are syntactically constrained; they are not simply arbitrary lines of code.

Decorators can be used on classes too

Python supports decorators on class definitions as well as functions. A class decorator receives the newly created class and the class name is bound to the object it returns. Class decorators were added in Python 3.0, as recorded in PEP 3129. The current language reference documents decorators for both function and class definitions.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Metaclasses can perform some kinds of class transformation, but they are not interchangeable with class decorators in every situation. PEP 3129 discusses decorator-like functionality implemented through metaclasses as potentially unpleasant and fragile; that is a design rationale, not a claim that every metaclass is inappropriate.

Why Python put the transformation beside the definition

Before decorator syntax, a transformation could be written as a reassignment after a function or method’s body. That placed the change away from the declaration it affected. PEP 318’s authors—Kevin D. Smith, Jim J. Jewett, Skip Montanaro, and Anthony Baxter—described the older approach this way: “The current method for transforming functions and methods (for instance, declaring them as a class or static method) is awkward and can lead to code that is difficult to understand.”

The @ form was intended to make the transformation visible next to the declaration. That improves proximity, but it does not explain what a particular decorator does; readers may still need to find its implementation or documentation.

Form Where the transformation appears What a reader must discover
Decorator syntax Beside the function or class declaration What the decorator changes and, if stacked, how the transformations compose
Explicit reassignment After the definition Which object is being reassigned and what the transformation does
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

So, are decorators “sus”?

The syntax itself is a compact way to express a transformation and rebinding; it does not signal that code is unsafe or dishonest. “Sus” is a fair reaction when a decorator hides consequential behavior, has an unclear name, or appears in a stack whose order is hard to reason about. The practical test is whether someone reading the declaration can identify the decorator’s effect and follow what object the name refers to afterward.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Function and method decorators arrived in Python 2.4; class decorators followed in Python 3.0. Those are historical milestones, not a recommendation to use decorators everywhere. Use the syntax when putting a meaningful transformation beside its definition makes the code easier to understand; if the behavior is hard to discover, the decorator deserves scrutiny, not the syntax alone.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.