On Wed, Aug 5, 2020 at 6:42 PM Steven D'Aprano <steve@pearwood.info> 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 <steve@pearwood.info> wrote:

> > 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
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.

--Guido van Rossum (python.org/~guido)