decorator keyword¶
decorator def declares a function that can be used as a decorator in three call shapes:
@d— direct decoration@d()— parens, no options@d(opt=...)— parens with options
the first positional parameter is the decorated callable. all other parameters must be keyword-only and have defaults — they are the decorator's options
decorator def d(fn: (...) -> object, option: bool = False) -> int:
return 1 if option else len(str(fn))
@d
def f1(): ...
@d()
def f2(): ...
@d(option=True)
def f3(): ...
rules¶
- the function must have at least one positional parameter — the decorated callable
- any remaining parameters are made keyword-only at the call site, and must have defaults
- the
fnparameter type is rendered asCallable[..., object]in the generated overloads regardless of the user-written annotation. the user-written annotation is preserved on the runtime impl for documentation but is not used for static call-site typing - the return type of the user-written function is preserved as the result type of applying the decorator
scope¶
decorator def is module-scope only. inside a class body the keyword is
rejected — class-method decorators don't need the keyword (use a normal
def returning a callable), and the synthesized overloads would shadow the
enclosing class's attribute namespace
why a keyword¶
a hand-written decorator that supports all three call shapes is tedious and easy to get wrong (sentinel handling, overload ordering, recursive dispatch). the keyword removes boilerplate and centralizes the pattern so the overloads always match the runtime impl