[Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part) (original) (raw)

Tim Peters tim.peters at gmail.com
Thu Jun 28 12:28:10 EDT 2018


[Chris Barker]

So what about:

l = [x:=i for i in range(3)] vs g = (x:=i for i in range(3)) Is there any way to keep these consistent if the "x" is in the regular local scope?

[Tim]

I'm not clear on what the question is. The list comprehension would bind l to [0, 1, 2] and leave the local x bound to 2. The second example binds g to a generator object, which just sits there unexecuted. That has nothing to do with the PEP, though.

If you go on to do, e.g., l = list(g) then, same as the listcomp, l will be bound to [0, 1, 2] and the local x will be left bound to 2.

[Chris]

OK, it has been said that the priority is that

list(agenexpression) Behave the same as [thesameexpression]

That's certainly desirable.

So we’re good there. And maybe it’s correct that leaving the running of the genexp ‘till later is pretty uncommon, particularly for newbies,

Common or not, I have no idea why anyone would write a genexp like the one you gave, except to contrive an example of silly behavior exhibited by silly code ;-)

It's really not interesting to me to make up code as goofy as you can conceive of - the interesting questions are about plausible code (including plausible coding errors).

but:

If the execution of the genexp is put off, it really confuses things — that name being changed would happen at some arbitrary tone, and at least in theory, the genexp could be passed off to somewhere else in the code, and be run or not run completely remotely from where the name is used.

Sure.

So while this is technically the same as the comprehension, it is not the same as a generator function which does get its own scope.

It is the same as a generator function with appropriate scope declarations

Then calling f() prints:

x before 12
L [0, 1, 2]
x after 2

And we should be clear how it will work — after all, in py2, the handling of the looping name was handled differently in genexp vs comprehensions.

The PEP specifies the semantics. If it's accepted, that will be folded into the docs.

So I think a local scope for all comprehension-like things would be the way to go.

But getting back to the original thread topic — python has a number of places that you can only use expressions — adding the ability to bind a name in all these places complicates the language significantly.

Did adding ternary if (truepart if expression else falsepart) complicate the language significantly? Python has rarely expanded the number of expression forms, but whenever it has the sky didn't actually fall despite earnest warnings that disaster was inevitable ;-)

Put a body B in a listcomp and any side effects due to executing B

Maybe it’s just me, but re-binding a name seems like a whole new category of side effect.

With no trickery at all, you've always been able to rebind attributes, and mutate containers, in comprehensions and genexps. Because for targets aren't limited to plain names; e.g.,

g = (x+y for object.attribute, a[i][j] in zip(range(3), range(3)))

is already "legal", and will stomp all over the complex for targets when executed - there's nothing "local" about them. But nobody worries about that because nobody does stuff like that.

And as in my goofy code above, mucking with binding of plain names is also possible today. Indeed, straightforward if that's what you want to do. But nobody does.

It's just not one of Python's goals to make it impossible to write useless code ;-) -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.python.org/pipermail/python-dev/attachments/20180628/63716a34/attachment.html>



More information about the Python-Dev mailing list