[Python-checkins] peps: Another major editing pass. Move __future__ into spec. Add section about
guido.van.rossum
python-checkins at python.org
Wed Nov 26 07:06:17 CET 2014
https://hg.python.org/peps/rev/574b60a51ebd
changeset: 5621:574b60a51ebd
user: Guido van Rossum <guido at python.org>
date: Tue Nov 25 22:05:29 2014 -0800
summary:
Another major editing pass. Move __future__ into spec. Add section about compatible code.
files:
pep-0479.txt | 75 +++++++++++++++++++++++++--------------
1 files changed, 47 insertions(+), 28 deletions(-)
diff --git a/pep-0479.txt b/pep-0479.txt
--- a/pep-0479.txt
+++ b/pep-0479.txt
@@ -14,10 +14,12 @@
Abstract
========
-This PEP proposes a backwards incompatible change to generators: when
-``StopIteration`` is raised inside a generator, it is replaced it with
-``RuntimeError``. (More precisely, this happens when the exception is
-about to bubble out of the generator's stack frame.)
+This PEP proposes a change to generators: when ``StopIteration`` is
+raised inside a generator, it is replaced it with ``RuntimeError``.
+(More precisely, this happens when the exception is about to bubble
+out of the generator's stack frame.) Because the change is backwards
+incompatible, the feature is initially introduced using a
+``__future__`` statement.
Rationale
@@ -100,6 +102,17 @@
using a ``try/except`` around the ``yield``), it will be transformed
into ``RuntimeError``.
+During the transition phase, the new feature must be enabled
+per-module using::
+
+ from __future__ import generator_stop
+
+Any generator function constructed under the influence of this
+directive will have the ``REPLACE_STOPITERATION`` flag set on its code
+object, and generators with the flag set will behave according to this
+proposal. Once the feature becomes standard, the flag may be dropped;
+code should not inspect generators for it.
+
Consequences for existing code
==============================
@@ -116,28 +129,34 @@
yield from helper()" rather than just "helper()".""")
There are also examples of generator expressions floating around that
-rely on a StopIteration raised by the expression, the target or the
-predicate (rather than by the __next__() call implied in the ``for``
+rely on a ``StopIteration`` raised by the expression, the target or the
+predicate (rather than by the ``__next__()`` call implied in the ``for``
loop proper).
-As this can break code, it is proposed to utilize the ``__future__``
-mechanism to introduce this in Python 3.5, finally making it standard
-in Python 3.6 or 3.7. The proposed syntax is::
+Writing backwards and forwards compatible code
+----------------------------------------------
- from __future__ import generator_stop
+With the exception of hacks that raise ``StopIteration`` to exit a
+generator expression, it is easy to write code that works equally well
+under older Python versions as under the new semantics.
-Any generator function constructed under the influence of this
-directive will have the REPLACE_STOPITERATION flag set on its code
-object, and generators with the flag set will behave according to this
-proposal. Once the feature becomes standard, the flag may be dropped;
-code should not inspect generators for it.
+This is done by enclosing those places in the generator body where a
+``StopIteration`` is expected (e.g. bare ``next()`` calls or in some
+cases helper functions that are expected to raise ``StopIteration``)
+in a ``try/except`` construct that returns when ``StopIteration``
+returns. The ``try/except`` construct should appear directly in the
+generator function; doing this in a helper function that is not itself
+a generator does not work. If ``raise StopIteration`` occurs directly
+in a generator, simply replace it with ``return``.
-Examples
---------
-Generators which explicitly raise StopIteration can generally be
+Examples of breakage
+--------------------
+
+Generators which explicitly raise ``StopIteration`` can generally be
changed to simply return instead. This will be compatible with all
-existing Python versions, and will not be affected by __future__.
+existing Python versions, and will not be affected by ``__future__``.
+Here are some illustrations from the standard library.
Lib/ipaddress.py::
@@ -164,7 +183,7 @@
(The ``return`` is necessary for a strictly-equivalent translation,
though in this particular file, there is no further code, and the
-``return`` can be elided.) For compatibility with pre-3.3 versions
+``return`` can be omitted.) For compatibility with pre-3.3 versions
of Python, this could be written with an explicit ``for`` loop::
if context is None:
@@ -172,10 +191,10 @@
yield line
return
-More complicated iteration patterns will need explicit try/catch
-constructs. For example, a parser construct like this::
+More complicated iteration patterns will need explicit ``try/except``
+constructs. For example, a hypothetical parser like this::
- def unwrap(f):
+ def parser(f):
while True:
data = next(f)
while True:
@@ -227,7 +246,7 @@
visible.
An iterator is an object with a ``__next__`` method. Like many other
-dunder methods, it may either return a value, or raise a specific
+special methods, it may either return a value, or raise a specific
exception - in this case, ``StopIteration`` - to signal that it has
no value to return. In this, it is similar to ``__getattr__`` (can
raise ``AttributeError``), ``__getitem__`` (can raise ``KeyError``),
@@ -271,9 +290,9 @@
deprecation warning if ``StopIteration`` bubbles out of a generator
not under ``__future__`` import.
-- Python 3.6: non-silent deprecation warning.
+- Python 3.6: Non-silent deprecation warning.
-- Python 3.7: enable new semantics everywhere.
+- Python 3.7: Enable new semantics everywhere.
Alternate proposals
@@ -363,12 +382,12 @@
issues inherent to every other case where an exception has special
meaning. For instance, an unexpected ``KeyError`` inside a
``__getitem__`` method will be interpreted as failure, rather than
-permitted to bubble up. However, there is a difference. Dunder
+permitted to bubble up. However, there is a difference. Special
methods use ``return`` to indicate normality, and ``raise`` to signal
abnormality; generators ``yield`` to indicate data, and ``return`` to
signal the abnormal state. This makes explicitly raising
``StopIteration`` entirely redundant, and potentially surprising. If
-other dunder methods had dedicated keywords to distinguish between
+other special methods had dedicated keywords to distinguish between
their return paths, they too could turn unexpected exceptions into
``RuntimeError``; the fact that they cannot should not preclude
generators from doing so.
--
Repository URL: https://hg.python.org/peps
More information about the Python-checkins
mailing list