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?