[Q] is 'yield from' syntax sugar for 'for'+'yield'?

2014-08-14 Thread Makoto Kuwata
Question about 'yield from'.

I understand that::

yield from xs

is syntax suger of::

for x in xs:
  yield x

And::

val = yield from xs

is same as::

for x in xs:
  ret = yield x
val = ret

Is it true? Do I understand correctly?


quote from
https://docs.python.org/3/whatsnew/3.3.html#pep-380-syntax-for-delegating-to-a-subgenerator
 For simple iterators, yield from iterable is essentially
 just a shortened form of for item in iterable: yield item:

--
regards,
kwatch
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [Q] is 'yield from' syntax sugar for 'for'+'yield'?

2014-08-14 Thread Chris Angelico
On Thu, Aug 14, 2014 at 7:35 PM, Makoto Kuwata kwa...@gmail.com wrote:
 I understand that::

 yield from xs

 is syntax suger of::

 for x in xs:
   yield x

Not just. It's like that for simple cases, but there are edge cases
that are much more complicated to do manually, and are simply taken
care of. Best would be to read the PEP itself:

http://www.python.org/dev/peps/pep-0380/

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [Q] is 'yield from' syntax sugar for 'for'+'yield'?

2014-08-14 Thread Makoto Kuwata
On Thu, Aug 14, 2014 at 6:38 PM, Chris Angelico ros...@gmail.com wrote:

 On Thu, Aug 14, 2014 at 7:35 PM, Makoto Kuwata kwa...@gmail.com wrote:
  I understand that::
 
  yield from xs
 
  is syntax suger of::
 
  for x in xs:
yield x

 Not just. It's like that for simple cases, but there are edge cases
 that are much more complicated to do manually, and are simply taken
 care of. Best would be to read the PEP itself:

 http://www.python.org/dev/peps/pep-0380/

 ChrisA


Thank you. It seems too complicated...
I understand that 'val = yield from xs' is completely different from::

   for x in xs:
  ret = yield x
   val = x

Return value is propagated by StopIteration, like:

   it = iter(xs)
   try:
 while 1:
   yield next(it)
   except StopIteration as ex:
 val = ex.value


Thanks.

--
regards,
kwatch
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [Q] is 'yield from' syntax sugar for 'for'+'yield'?

2014-08-14 Thread Marko Rauhamaa
Makoto Kuwata kwa...@gmail.com:

 val = yield from xs

 is same as::

 for x in xs:
   ret = yield x
 val = ret

 Is it true? Do I understand correctly?

The return value is not one of the yielded values. Instead, it's the
value returned by the generator/coroutine.


Marko
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [Q] is 'yield from' syntax sugar for 'for'+'yield'?

2014-08-14 Thread Chris Angelico
On Thu, Aug 14, 2014 at 7:59 PM, Makoto Kuwata kwa...@gmail.com wrote:
 I understand that 'val = yield from xs' is completely different from::

for x in xs:
   ret = yield x
val = x

 Return value is propagated by StopIteration, like:

it = iter(xs)
try:
  while 1:
yield next(it)
except StopIteration as ex:
  val = ex.value

It's even more complicated than that. The PEP specifies the exact semantics.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [Q] is 'yield from' syntax sugar for 'for'+'yield'?

2014-08-14 Thread Marko Rauhamaa
Makoto Kuwata kwa...@gmail.com:

 Thank you. It seems too complicated...

I recommend you stop trying to associate the old yield with the new
yield.

Asyncio coroutines abuse yield from for a specific effect. The
classic purpose of yield was to spoonfeed a sequence of return values
to the caller. The coroutine meaning of yield from has nothing
whatsoever to do about delivering computation results; instead, it
denotes a state where a blocking operation is waited for and the control
is handed off to other activities.



Marko
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [Q] is 'yield from' syntax sugar for 'for'+'yield'?

2014-08-14 Thread Makoto Kuwata
On Thu, Aug 14, 2014 at 7:02 PM, Chris Angelico ros...@gmail.com wrote:

 On Thu, Aug 14, 2014 at 7:59 PM, Makoto Kuwata kwa...@gmail.com wrote:
  I understand that 'val = yield from xs' is completely different from::
 
 for x in xs:
ret = yield x
 val = x
 
  Return value is propagated by StopIteration, like:
 
 it = iter(xs)
 try:
   while 1:
 yield next(it)
 except StopIteration as ex:
   val = ex.value

 It's even more complicated than that. The PEP specifies the exact
 semantics.

 ChrisA


Well, I wrote the above code in order to describe `value is propagated by
StopIteration'
because I misunderstood that it is propagated by return value of yield
statement
(see my first post).

I have known that `yield from` is very complicated (thanks to your reply).

--
regards,
kwatch
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [Q] is 'yield from' syntax sugar for 'for'+'yield'?

2014-08-14 Thread Steven D'Aprano
Makoto Kuwata wrote:

 Question about 'yield from'.
 
 I understand that::
 
 yield from xs
 
 is syntax suger of::
 
 for x in xs:
   yield x

Not quite syntactic sugar. For simple cases, it does exactly the same thing.
For more complicated cases, no.

Suppose you have a generator:

def spam():
yield Spam!
yield More spam!
yield Delicious spam!!!

and you have another generator which delegates to the spam generator:

def lunch1():
for food in spam():
yield food
yield plus a fried egg


We can now re-write the generator using yield from:

def lunch2():
yield from spam()
yield plus a fried egg

That saves one line of code. Big deal. Here, it is pure syntactic sugar.

There are more interesting cases, where yield from is more powerful than
the for-loop version. Here is an example with throw:

py it = lunch1()  # Create an iterator.
py next(it)
'Spam!'
py it.throw(ValueError)
Traceback (most recent call last):
  File stdin, line 1, in module
  File stdin, line 3, in lunch1
ValueError

Notice that the ValueError is raised inside lunch1(). There is no easy way
to push the exception back inside spam(). But with yield from, it works:

py it = lunch2()  # New yield from generator.
py next(it)
'Spam!'
py it.throw(ValueError)
Traceback (most recent call last):
  File stdin, line 1, in module
  File stdin, line 2, in lunch2
  File stdin, line 2, in spam
ValueError


Of course, spam() is free to catch the exception and perform processing.



 And::
 
 val = yield from xs
 
 is same as::
 
 for x in xs:
   ret = yield x
 val = ret

No. This is closer to what happens:


# Not exactly this.
# This is a simplified version.
try:
for x in xs:
yield x
except StopIteration as err:
val = err.value


The real version is much more complicated, 39 lines of code, and deals with
generator .close() and .throw() methods, error checking, and various other
issues. That is why yield from was added to Python. The simple case is
too simple to care about, the complicated cases are too complicated to
expect people to write their own solutions, so it was added to the
language.



-- 
Steven

-- 
https://mail.python.org/mailman/listinfo/python-list