More clarifications in response to Oscar Benjamin.
This commit is contained in:
parent
b142f8f22d
commit
4af42e2b28
28
pep-0479.txt
28
pep-0479.txt
|
@ -43,13 +43,16 @@ The interaction of generators and ``StopIteration`` is currently
|
|||
somewhat surprising, and can conceal obscure bugs. An unexpected
|
||||
exception should not result in subtly altered behaviour, but should
|
||||
cause a noisy and easily-debugged traceback. Currently,
|
||||
``StopIteration`` can be absorbed by the generator construct.
|
||||
``StopIteration`` raised accidentally inside a generator function will
|
||||
be interpreted as the end of the iteration by the loop construct
|
||||
driving the generator.
|
||||
|
||||
The main goal of the proposal is to ease debugging in the situation
|
||||
where an unguarded ``next()`` call (perhaps several stack frames deep)
|
||||
raises ``StopIteration`` and causes the iteration controlled by the
|
||||
generator to terminate silently. (When another exception is raised, a
|
||||
traceback is printed pinpointing the cause of the problem.)
|
||||
generator to terminate silently. (Whereas, when some other exception
|
||||
is raised, a traceback is printed pinpointing the cause of the
|
||||
problem.)
|
||||
|
||||
This is particularly pernicious in combination with the ``yield from``
|
||||
construct of PEP 380 [1]_, as it breaks the abstraction that a
|
||||
|
@ -352,7 +355,9 @@ iterators: a generator object is still an iterator, and not all
|
|||
iterators are generators. Generators have additional methods that
|
||||
iterators don't have, like ``send`` and ``throw``. All this is
|
||||
unchanged. Nothing changes for generator users -- only authors of
|
||||
generator functions may have to learn something new.
|
||||
generator functions may have to learn something new. (This includes
|
||||
authors of generator expressions that depend on early termination of
|
||||
the iteration by a ``StopIteration`` raised in a condition.)
|
||||
|
||||
An iterator is an object with a ``__next__`` method. Like many other
|
||||
special methods, it may either return a value, or raise a specific
|
||||
|
@ -489,6 +494,10 @@ block of code which reliably works on multiple versions of Python.
|
|||
(Using a dedicated exception type, perhaps subclassing ``ValueError``,
|
||||
would help this; however, all code would still need to be rewritten.)
|
||||
|
||||
Note that calling ``next(it, default)`` catches ``StopIteration`` and
|
||||
substitutes the given default value; this feature is often useful to
|
||||
avoid a ``try/except`` block.
|
||||
|
||||
|
||||
Sub-proposal: decorator to explicitly request current behaviour
|
||||
---------------------------------------------------------------
|
||||
|
@ -556,6 +565,17 @@ their return paths, they too could turn unexpected exceptions into
|
|||
``RuntimeError``; the fact that they cannot should not preclude
|
||||
generators from doing so.
|
||||
|
||||
Why not fix all __next__() methods?
|
||||
-----------------------------------
|
||||
|
||||
When implementing a regular ``__next__()`` method, the only way to
|
||||
indicate the end of the iteration is to raise ``StopIteration``. So
|
||||
catching ``StopIteration`` here and converting it to ``RuntimeError``
|
||||
would defeat the purpose. This is a reminder of the special status of
|
||||
generator functions: in a generator function, raising
|
||||
``StopIteration`` is redundant since the iteration can be terminated
|
||||
by a simple ``return``.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
|
Loading…
Reference in New Issue