[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