Generator function that always processes, but does not always yield

时间:2019-04-08 13:19:55

标签: python-3.x generator python-3.7

I have a generator function that does 2 things:

  1. Reads a file and writes another file based on the output.
  2. Yields key values for the record it's just written.

The issue is that I don't always want to do point (2), and when I call it in such a way that I only want the lines written to a new file, it simply doesn't get called (i.e. a print statement as the first line does not even get output. Try/except catches nothing here either when it's called).

I've set up a simplified test case just to verify that this is "normal", and it reproduces the same results.

test.py

from test2 import run_generator

if __name__ == '__main__':
    print('*** Starting as generator ***')
    for num in run_generator(max=10, generate=True):
        print(f'Calling  : {num}')

    print('*** Starting without yielding ***')
    run_generator(max=10, generate=False)

    print('*** Finished ***')

test2.py

def run_generator(max, generate):
    print('*** In the generator function ***')
    sum = 1
    for i in range(max):
        print(f'Generator: {i}')
        sum += i

        if generate:
            yield i

    print(f'End of generator, sum={sum}')

This gives me the output:

$ python3 test.py
*** Starting as generator ***
*** In the generator function ***
Generator: 0
Calling  : 0
Generator: 1
Calling  : 1
Generator: 2
Calling  : 2
Generator: 3
Calling  : 3
Generator: 4
Calling  : 4
Generator: 5
Calling  : 5
Generator: 6
Calling  : 6
Generator: 7
Calling  : 7
Generator: 8
Calling  : 8
Generator: 9
Calling  : 9
End of generator, sum=46
*** Starting without yielding ***
*** Finished ***

In the test example, I'd like the generator function to still print the values when called but told not to yield. (In my real example, I still want it to do a f.write() to a different file, under which everything is nested since it's an with open(file, 'w') as f: statement.

Am I asking it to do something stupid? The alternative seems to be 2 definitions that do almost the same thing, which violates the DRY principle. Since in my primary example the yield is nested within the "with open", it's not really something that can be pulled out of there and done separately.

1 个答案:

答案 0 :(得分:1)

it simply doesn't get called - it's because you don't call it. To solve the problem call it like any other generator. For example, like you did in the first case: for num in run_generator(max=10, generate=False): pass.

I guess, another way is to use next(run_generator(max=10, generate=False)) syntax inside try/except since yield is never reached so you will get StopIteration error.

Or something like result = list(run_generator(5, True/False)).