[Python-ideas] Inline assignments using "given" clauses

Tim Peters tim.peters at gmail.com
Mon May 14 06:10:47 EDT 2018


[Greg Ewing <greg.ewing at canterbury.ac.nz>']
> This whole discussion started because someone wanted a way
> to bind a temporary result for use *within* a comprehension.

It's been noted several times recently that the example PEP 572 gives
as _not_ working:

    total = 0
    progressive_sums = [total := total + value for value in data]

was the original use case that prompted work on the PEP.  You gotta
admit that's ironic ;-)


> Those use cases don't require leakage.

I already said that - yes - some use cases don't want the leakage.
Others do.  And the vast majority of listcomps/genexps will likely
never use an assignment expression anyway.  If "no leak" wins, "want
leak" can't do what they want at all.  If "want leak" wins, the
subset-of-a-subset "no leak" cases are inconvenienced.

As I said, it's a tradeoff.  You're giving 0 weight to one of the sides.


>> Otherwise it's essentially impossible to explain why:
>>
>>     total = 0
>>     sums = [total := total + value for value in data]
>>     assert sums[-1] == total
>>
>> "blows up", despite that its intent is obvious,unless you first
>> explain to a user how the listcomp is implemented via an invisible
>> synthetic function created by magic, inside of which `total`  has
>> nothing to do with the `total` they see on the first line.

> It's no harder to explain that than it is to explain
> why
>
>    x = 42
>    y = [x * x for x in range(5)]
>    print(x)
>
> prints 42 rather than whatever value was last bound to
> the x in the comprehension.

You're overlooking the most relevant point:  The example blows with an
UnboundLocalError, which can't possibly be explained by looking at the
example as it stands, or by reference to shallow tricks.  You _need_
to drag in stuff about invisible (in the code) synthesized scopes in
which `total` is in fact an unbound local name.

You don't need that heavy machinery to explain why for-target names
don't leak; indeed, shallow implementation tricks were used to achieve
that well before synthetic functions _were_ used to implement
listcomps.


> Seems to me it would be easier to explain that *all* names
> bound within a comprehension are local to the comprehension,
> than to have to say that some are and some aren't.

for-targets are local, assignment expression targets aren't.  I agree
that's harder to explain, but on a scale of 1 to 10?  1.

It's a tradeoff.  And I cheerfully just gave 1 point to the side you
favor.  By my accounting, "leak" is still wining by about 136 to 17
;-)


More information about the Python-ideas mailing list