On Wed, Aug 5, 2020 at 6:42 PM Steven D'Aprano email@example.com wrote:
On Wed, Aug 05, 2020 at 06:15:22PM -0700, Guido van Rossum wrote:
On Wed, Aug 5, 2020 at 5:55 PM Steven D'Aprano firstname.lastname@example.org
That require two different rules for decorators:
@decorator over a `class name` or `def name` statement:
- execute the statement
- bind `name = decorator(name)`
But that's not what's done. (Proof: if the decorator raises, the name remains unbound.)
You are technically correct, which is the best kind of correct.
The documentation uses very close to the same wording as me
but does make the point that "except that the original function is not temporarily bound to the name func". Since I wasn't writing a reference manual, I didn't think this level of pedantry was needed :-)
The bottom line is that the function or class statement has to be executed *in some sense* in order to create the function or class object, that object has to be passed to the decorator, and finally the object returned by the decorator has to be bound to the original name.
But that's the same as it would be for a decorated assignment, right? In ``` @deco x = func(arg) ``` This executes `func(arg)` to create the value of the expression, then passes it to the decorator, and finally the decorator's result is bound to the name `x`.
In both cases there's something that gets executed to create something (in one case, a function or class object, in another case, some other object), and then gets bound to a name; in both cases a decorator, if present, is inserted to transform the value just before it is bound.
A much better argument against decorating assignments is that you can already write it just fine as ``` x = deco(func(arg)) ``` and the decorated version is in no way more readable, nor does it provide more power or expressivity. For functions and classes, the old way was ``` def f(a, b, c): <20 lines of body code> f = deco(f) ``` which hides the decorator call where it is easily overlooked (especially by people who are quickly scanning code for function definitions). The decorator syntax was introduced so that the transformation could be placed where it is noticed by the reader.
Another way of looking at the difference between decorating expressions vs. decorating function/class definitions would be that syntactically, `def` and `class` statements are multi-line definitions, so that it makes sense that a modifier should be placed on a line by itself; whereas assignments are single-line definitions, so that modifiers should also be placed in-line.