PEP 572: Add migration notes
This commit is contained in:
parent
423b65b131
commit
9e5e64814a
70
pep-0572.rst
70
pep-0572.rst
|
@ -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
|
||||
============================
|
||||
|
||||
|
|
Loading…
Reference in New Issue