[Python-ideas] PEP 572: Statement-Local Name Bindings

Chris Angelico rosuav at gmail.com
Wed Feb 28 14:47:11 EST 2018


On Thu, Mar 1, 2018 at 5:09 AM, Rob Cliffe via Python-ideas
<python-ideas at python.org> wrote:
>
>
> On 28/02/2018 05:23, Chris Angelico wrote:
>>
>>
>>> If calling `f(x)` is expensive or has side effects, the clean operation
>>> of
>>> the list comprehension gets muddled. Using a short-duration name binding
>>> retains the simplicity; while the extra `for` loop does achieve this, it
>>> does so at the cost of dividing the expression visually, putting the
>>> named
>>> part at the end of the comprehension instead of the beginning.
>>>
>>> Maybe add to last sentence "and of adding (at least conceptually) extra
>>> steps: building a 1-element list, then extracting the first element"
>>
>> That's precisely the point that Serhiy's optimization is aiming at,
>> with the intention of making "for x in [expr]" a standard idiom for
>> list comp assignment. If we assume that this does become standard, it
>> won't add the extra steps, but it does still push that expression out
>> to the far end of the comprehension, whereas a named subexpression
>> places it at first use.
>
> I understand that creating the list could be avoided *at runtime*. My point
> was that in trying to *read and understand*
>         stuff = [[y, y] for x in range(5) for y in [f(x)]]
> the brain must follow the creation and unpacking of the list.  I.e. this is
> an extra cost of this particular construction.
>>
>>
>>> And here's a thought: What are the semantics of
>>>      a = (42 as a) # Of course a linter should point this out too
>>> At first I thought this was also a laborious synonym for "a=42".  But
>>> then I
>>> re-read your statement (the one I described above as crystal-clear) and
>>> realised that its exact wording was even more critical than I had
>>> thought:
>>>      "the new name binding will shadow the other name from the point
>>> where it
>>> is evaluated until the end of the statement"
>>> Note: "until the end of the statement".  NOT "until the end of the
>>> expression".  The distinction matters.
>>> If we take this as gospel, all this will do is create a temporary
>>> variable
>>> "a", assign the value 42 to it twice, then discard it.  I.e. it
>>> effectively
>>> does nothing, slowly.
>>> Have I understood correctly?  Very likely you have considered this and
>>> mean
>>> exactly what you say, but I am sure you will understand that I mean no
>>> offence by querying it.
>>
>> Actually, that's a very good point, and I had to actually go and do
>> that to confirm. You're correct that the "a =" part is also affected,
>> but there may be more complicated edge cases.
>
> I have read this thread so far - I can't say I have absorbed and understood
> it all, but I am left with a feeling that Expression-Local-Name-Bindings
> would be preferable to Statement-Local-Name_Bindings, so that the temporary
> variable wouldn't apply to the LHS in the above example.  I realise that
> this is a vague statement that needs far more definition, but - hand-waving
> for now - do you think it would be difficult to change the implementation
> accordingly?
>

Yes it would, but AIUI (I haven't tested it) a competing
implementation already exists. So now we just need a competing PEP and
we can run with it!

ChrisA


More information about the Python-ideas mailing list