Bruno Vermeulen
Bruno Vermeulen

Reputation: 3455

Yield and yield from - can you combine them?

Just found out about the yield from construct, which to my idea is somewhat like a reversed yield, instead of getting an object out of a generator, you insert/ send an object to a generator. Like:

def foo():
    while True:
        x = (yield)
        print(f'{x=}')

f = foo()
f.send(None)
for i in range(4):
    f.send(i)

yields:

x=0
x=1
x=2
x=3

So then I wondered if you can combine the two.

def foo():
    while True:
        x = (yield)
        print(f'{x=}')
        yield x + 1000

f = foo()
f.send(None)
for i in range(4):
    print(f'y={f.send(i)}')

Then I would expect

x=0
y=1000
x=1
y=1001
x=2
y=1002
x=3
y=1003

but I get

x=0
y=1000
y=None
x=2
y=1002
y=None

Anyone can explain this?

Upvotes: 2

Views: 241

Answers (1)

UltraInstinct
UltraInstinct

Reputation: 44444

If you'd 'combine the two', it's useful to think of yield as a single point of sending values out, and then accepting values in from outside. That way, you might appreciate why you don't get a line printing out "x=" every alternate line and get Nones every third line in your output. This is because the control comes out of foo(..) two times every loop in the while block.

Here's the fixed version of your code:

def foo():
    x = 0
    while True:
        x = (yield x + 1000)
        print(f'{x=}')

f = foo()
f.send(None)
for i in range(4):
    print(f'y={f.send(i)}')

Upvotes: 3

Related Questions