0

I know it never use to write several return statements sequentially bc the second one will be unreachable, eg:

def return_something():
    return 2
    return "Kolia" # unreachable

But if there any use to write several yield statement sequentially?

def yield_something():
    yield 3
    yield 4

print(next(yield_something()))
print(next(yield_something()))

>>> 3 
>>> 3

Seems to me I have seen somewhere use of sequential yield and my IDE doesn't highlighting it. Could anyone expose to me use of sequential yield?

Rudziankoŭ
  • 8,411
  • 10
  • 66
  • 146

4 Answers4

4

Sequential yield could be a replacement for, or replaced by, yielding the values in a constant tuple.

for i in (1,7,3,20):
    yield i

# versus

yield 1; yield 7; yield 3; yield 20

Alternatively, you might have more than one yield in your code, doing different things. I wouldn't consider these sequential yields so much as two parts of a larger function:

def unzip_dict(d):
    for k in d.keys():
        yield k
    for v in d.values():
        yield v
aghast
  • 13,113
  • 1
  • 16
  • 44
3

You always create a new generator when using yield_something(). You should create one generator: a = yield_something() and then call next(a) on that generator:

def yield_something():
    yield 3
    yield 4

a = yield_something() # Generator
print(next(a)) # 3
print(next(a)) # 4

But generally you define a loop inside the generator that generates the yields:

def yield_something():
    for i in (3,4):
        yield i

or if they can be computed then the generator is really powerful because it doesn't need to keep the list of values in memory:

def yield_something():
    i = 3
    while i < 5:
        yield i
        i += 1
MSeifert
  • 118,681
  • 27
  • 271
  • 293
2

The following exposes the use of the sequential yield in your example:

def yield_something():
    yield 3
    yield 4

a = yield_something()
print(next(a))
print(next(a))

Output

3
4

In your example, each time you call yield_something() you create a new generator. Create a generator using a = yield_something() and then use next() each time you want to yield.

gtlambert
  • 10,708
  • 2
  • 27
  • 45
2

Yes, there are even real word examples. If you take a look at this prime sieve implementation here on StackOverflow, you see that it uses sequential yields. Although it's true it's used only as an optimization here.

The following code is copeid from tzot's answer:

import itertools as it
def erat3( ):
    D = { 9: 3, 25: 5 }
    yield 2
    yield 3
    yield 5
    MASK= 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0,
    MODULOS= frozenset( (1, 7, 11, 13, 17, 19, 23, 29) )

    for q in it.compress(
            it.islice(it.count(7), 0, None, 2),
            it.cycle(MASK)):
        p = D.pop(q, None)
        if p is None:
            D[q*q] = q
            yield q
        else:
            x = q + 2*p
            while x in D or (x%30) not in MODULOS:
                x += 2*p
            D[x] = p
Community
  • 1
  • 1
Tamas Hegedus
  • 24,663
  • 9
  • 48
  • 87