3

I was going through this SO question on the generator send function when I came across this code

def coroutine():
    for i in range(1, 10):
        print("From generator {}".format((yield i)))
c = coroutine()
c.send(None)
try:
    while True:
        print("From user {}".format(c.send(1)))
except StopIteration: pass

As you can see the author used braces around the yield i; and I don't understand why it is needed.

The doc for str.format() doesn't mention anything about the argument to format() to be of any type. I'm sure my confusion arises from the fact that I don't know what the yield statement does or what type is generated or made when it's called.

Can you help me understand why braces are needed around the yield in a str.format function call?

The compiler wasn't very helpful and so I had to ask this question

In [1]: def coroutine():
   ...:     for i in range(1, 10):
   ...:         print("From generator {}".format(yield i))
   ...: c = coroutine()
   ...: c.send(None)
   ...: try:
   ...:     while True:
   ...:         print("From user {}".format(c.send(1)))
   ...: except StopIteration: pass
  File "<ipython-input-1-024981190f27>", line 3
    print("From generator {}".format(yield i))
                                         ^
SyntaxError: invalid syntax
clamentjohn
  • 3,417
  • 2
  • 18
  • 42
  • I would say it is similar to the case `sum(i for i in range(3),0)` (syntax error) vs `sum((i for i in range(3)),0)` (ok). In certain circumstances, python require "extra" braces, even from human point of view they are not needed – Jan Stránský Sep 01 '20 at 07:39
  • Syntax error means it has nothing to do with `str.format`; the `yield` statement must be in parentheses (not braces) within an expression. – TigerhawkT3 Sep 01 '20 at 07:39
  • 1
    `yield i` is a statement. `format` arguments need to be expressions. By wrapping `yield i` with braces you turn it into an expression – Tomerikoo Sep 01 '20 at 07:41
  • 1
    For future reference, everything after a syntax error is unrelated to the error. 90% of this question is obfuscation; an [MCVE](http://stackoverflow.com/help/mcve) would've just compared e.g. `def f(): 0 + yield i` vs `def f(): 0 + (yield i)`. – TigerhawkT3 Sep 01 '20 at 07:56
  • @TigerhawkT3 Thank you. I was clearly looking at the wrong places to find an answer for this error. But @francis_duvivier's and @Tomerikoo's answer clearly points me to the right direction. That `yield is a statement` and format arguments need to be expressions. But deciding to keep the question up - because there weren't many resources on the internet that helped me. – clamentjohn Sep 01 '20 at 08:01

1 Answers1

2

In the referenced generator article, you can read:

I recommend that you always put parentheses around a yield expression when you're doing something with the returned value, as in the above example. The parentheses aren't always necessary, but it's easier to always add them instead of having to remember when they're needed. (PEP 342 explains the exact rules, which are that a yield-expression must always be parenthesized except when it occurs at the top-level expression on the right-hand side of an assignment.

So, since the returned value of yield i is used in and yield i is not a top-level expression on the right-hand side of an assignment, it must be parenthesized.

Also, some more info in this answer: https://stackoverflow.com/a/37845447/4962858

francis duvivier
  • 2,056
  • 11
  • 17