A decorator has more obvious semantics. For example, how would you annotate a deprecated class? You might say that you need to deprecate the __init__
or __new__
method, but what if you’re deprecating an Enum, Protocol, or dataclass without such a method? Or what if you’re deprecating a class’s public constructor, but not the class itself?
More broadly, with a deprecated function, it’s the function itself that’s deprecated, not the type. The PEP is quite explicit that any usage of a deprecated function should be flagged (e.g., map(deprecated_func, ...)
, not just calls.
As for putting the decorator into warnings
, I think that would be misleading. The primary purpose of the decorator is to interface with type checkers; the fact that it also (optionally) emits a runtime warning is just a bonus feature.
I feel strongly that a decorator is the clearest way to mark deprecated classes and functions, which appears to be the most common need. I welcome a follow-up PEP for expanding the feature set for deprecations, but I’d like to keep PEP 702 more focused.