Guido van Rossum writes:
        And my mind boggles when considering a generator expression
        containing yield that is returned from a function. I tried this
        and cannot say I expected the outcome:

            def f():
                return ((yield i) for i in range(3))
            print(list(f()))

        In both Python 2 and Python 3 this prints

            [0, None, 1, None, 2, None]

        Even if there's a totally logical explanation for that, I still
        don't like it, and I think yield in a comprehension should be
        banned. From this it follows that we should also simply ban
        yield  from comprehensions.


Serhiy Storchaka writes:
    This behavior doesn't look correct to me and Ivan.
The behavior is surprising, but it seems quite consistent with how generator expressions are defined in the language. A generator expression is defined by the language reference as "compact generator notation in parentheses", which yields (sic!) a "new generator object".

I take that to mean that a generator expression is equivalent to defining and calling a generator function. f() can be transformed to:

def f():
    def _gen():
        for i in range(3):
            ret = yield i
            yield ret
    return _gen()

The transformed version shows that there are *two* yields per iteration (one explicitly written and one inserted by the transformation), which is the reason why 6 values are produced. The None values come from list constructor calling __next__() on the generator, which (as per documentation) sends None into the generator. This None value is yielded after the "i" is yielded, which is why Nones follow the numbers.

Hrvoje
_______________________________________________
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

Reply via email to