PEP 572: Add migration notes

This commit is contained in:
Chris Angelico 2018-04-11 15:16:15 +10:00
parent 423b65b131
commit 9e5e64814a
1 changed files with 70 additions and 0 deletions

View File

@ -372,6 +372,76 @@ in a statement; alternatively, a new keyword is needed, with all the costs
therein.
Migration path
==============
The semantic changes to list/set/dict comprehensions, and more so to generator
expressions, may potentially require migration of code. In many cases, the
changes simply make legal what used to raise an exception, but there are some
edge cases that were previously legal and are not, and a few corner cases with
altered semantics.
Yield inside comprehensions
---------------------------
As of Python 3.7, the outermost iterable in a comprehension is permitted to
contain a 'yield' expression. If this is required, the iterable (or at least
the yield) must be explicitly elevated from the comprehension::
# Python 3.7
def g():
return [x for x in [(yield 1)]]
# With PEP 572
def g():
sent_item = (yield 1)
return [x for x in [sent_item]]
This more clearly shows that it is g(), not the comprehension, which is able
to yield values (and is thus a generator function). The entire comprehension
is consistently in a single scope.
Name lookups in class scope
---------------------------
A comprehension inside a class previously was able to 'see' class members ONLY
from the outermost iterable. Other name lookups would ignore the class and
potentially locate a name at an outer scope:
pattern = "<%d>"
class X:
pattern = "[%d]"
numbers = [pattern % n for n in range(5)]
In Python 3.7, ``X.numbers`` would show angle brackets; with PEP 572, it would
show square brackets. Maintaining the current behaviour here is best done by
using distinct names for the different forms of ``pattern``, as would be the
case with functions.
Generator expression bugs can be caught later
---------------------------------------------
Certain types of bugs in genexps were previously caught more quickly. Some are
now detected only at first iteration::
gen = (x for x in rage(10)) # NameError
gen = (x for x in 10) # TypeError (not iterable)
gen = (x for x in range(1/0)) # Exception raised during evaluation
This brings such generator expressions in line with a simple translation to
function form::
def <genexp>():
for x in rage(10):
yield x
gen = <genexp>() # No exception yet
tng = next(gen) # NameError
To detect these errors more quickly, ... TODO.
Frequently Raised Objections
============================