I have a generator function that does 2 things:
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.
答案 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))
.