[Python-ideas] Moving return above statements [was Re: Syntax for defining parametric decorators]

Nick Coghlan ncoghlan at gmail.com
Thu Jul 12 05:49:14 CEST 2012


On Thu, Jul 12, 2012 at 11:37 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> Looking back at "in return", here's a simple example which doesn't use
> nested functions. Compare:
>
>
> def function(arg):
>     in return value
>     value = process(arg)
>     print("Value is", value)

Like a decorator line, the "in" clause is effectively part of the
subsequent function/class definition - it's not a separate statement.
That's why there's no ending colon. However, I'm now thinking a
leading @ might be appropriate in order to make the decorator parallel
crystal clear.

> I would not describe that as "out-of-order". Seems to me that it is
> precisely in order: first you create the object (a function), then you
> return it. You can't return something before it exists.

No, that's implementation order - it's not "pattern of thought" order.
It's why English permits phrase like "this statement is true, given
that this particular assumption is true". You can forward reference
incidental details and fill them in later.

Sorting is generally a better example:

    x = sorted(container)

OK, this is sorted smallest to largest.

Now, I want to sort according to the second item. I can do this out of
order by introducing a key function before it's clear why I need it:

    def _key(v):
        return v[1]
    x = sorted(container, key=_key)

Or, we can use the awkward itemgetter construct to get things back in
the right order and restore the assignment and sorting operation to
it's rightful place of prominence:

    from operator import itemgetter
    x = sorted(container, key=itemgetter(1))

Using a lambda expression achieves the same goal:

    x = sorted(container, key=lambda v: v[1])

Those are both ugly though, and are restricted to a single expression.
More complicated sorting logic is forced back into using the out of
order form.

PEP 403 is designed to let you pull the sort key out into a trailing
full-fledged function definition:

    @in x = sorted(container, key=f)
    def f(v):
        return v[1]

The important part here is that the container is being sorted and the
result assigned to 'x' - the exact sort key used isn't important to
the overall flow of the algorithm.


> It seems to me that this proposal, and the older PEP 3150, are the ones
> which are out-of-order: you use things before they are defined.

Yes, both PEP 403 and 3150 are out of order from a code *execution*
point of view - but they're designed to match *patterns of thought*
that work that way. It's especially prevalent in callback based
programming - you end up with a lot of one-shot functions that aren't
actually all that important in their own right, what really matters is
the call you're handing them over to.

Sometimes you're only defining a separate function because that's the
only syntax Python has for passing a piece of code to a function, even
though the code is only used once.

Decorators eliminated this problem for the "f = deco(f)" and "C =
deco(C)" cases by baking the ability to make such calls into function
and class definitions. PEP 403 is solely about extending that same
capability to arbitrary simple statements.

> For what it's worth, I have slightly warmed to PEP 3150 and would give it a
> very tentative +0.125:

PEP 3150 died mainly due to "If the implementation is hard to explain,
it's a bad idea", but also due to the fact that you regularly ended up
with double-indents for callback based code. PEP 403 only has to a
support a statement local reference to a single name, which is
comparatively easy.

> (Aside: I actually prefer that bikeshed to be called "where" rather than
> "given".)

PEP 3150 has an entire section devoted to the reasons "where" isn't a
viable choice (not that that PEP stands any realistic chance of ever
being resurrected).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia



More information about the Python-ideas mailing list