On 30 November 2014 at 12:31, Chris Angelico <ros...@gmail.com> wrote: > On Sun, Nov 30, 2014 at 1:04 PM, Jim J. Jewett <jimjjew...@gmail.com> wrote: >> (4) It can happen because of "yield from" yielding from an iterator, >> rather than a generator? > > No; as I understand it (though maybe I'm wrong too), "yield from" will > yield every value the other iterator yields, and will then quietly > emit a value if the iterator raises StopIteration, or will allow any > other exception to propagate. The StopIteration coming from the > iterator is absorbed by the "yield from" construct. To completely > propagate it out, "return (yield from iter)" should cover all three > results (yielded value, returned value, raised exception).
Chris is correct here. The key yield from related change due to PEP 479 is to eliminate a subtle difference in the interaction between generators and StopIteration that currently exists when delegating to a subgenerator. If you throw StopIteration directly into a suspended generator, it propagates back out: >>> def gen1(): ... yield 1 ... yield 2 ... >>> g = gen1() >>> next(g) 1 >>> g.throw(StopIteration) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in gen1 StopIteration However, if the generator is instead suspended inside a *subgenerator*, then the thrown in exception will terminate the subgenerator, and execution of the delegating generator will resume: >>> def gen_inner(): ... yield 1 ... >>> def gen_outer(): ... yield from gen_inner() ... yield 2 ... >>> g2 = gen_outer() >>> next(g2) 1 >>> g2.throw(StopIteration) 2 Under PEP 479, the StopIteration thrown in StopIteration will be turned into RuntimeError regardless of whether or not a subgenerator is involved - the difference in the subgenerator case is that the transformation will happen when the innermost generator is terminated, and it will then appear as RuntimeError in the delegating generator. This change in semantics will make it possible to fix a latent defect in contextlib.contextmanager, where using a subgenerator as part of the context manager implementation may currently lead to inadvertently suppressing StopIteration in the body of a covered with statement. Regards, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com