+ 4

How do I know if a generator object generates output?

Look at this code: https://code.sololearn.com/clfz9prfS87c In line 40, I created a generator object (res). I know that I can use next() or a for each loop to iterate over the objects that the generator yields/returns (that's what I do in lines 42-45), but how can I tell whether or not the generator object actually returns something? I hope you get what I mean... Something like len(res) to see that the generator returns two objects (but that doesn't work). E.g., in the code linked above, the generator won't return anything for the range 0-1000. So if I try to iterate over the returned objects, nothing will happen. I use a boolean variable (f, lines 41/43) to check whether there is any output or not. But there has to be a more elegant way?

22nd Jul 2018, 8:30 AM
Anna
Anna - avatar
9 Answers
+ 8
I realize this is old, but perhaps this will still be interesting. Where you have: f = False for r in res: f = True print('{}:'.format(r)) showCalculation(r) print('These are all' if f ...) A list comprehension can replace the loop and flag, yielding an automatic len(): shows = [(print('{}:'.format(r)), showCalculation(r)) for r in res] print('These are all' if len(shows) ...) The list's length accurately represents the generator's iteration count, containing one tuple: (None,None) for each output, using trivial memory. In my opinion this is cleaner than the various 'workarounds' used to modify generators (especially a lambda generator)
13th Aug 2018, 10:05 PM
Kirk Schafer
Kirk Schafer - avatar
+ 3
𝕾𝖆𝖌𝖆𝕿𝖍𝖊𝕲𝖗𝖊𝖆𝖙 💯 I used the short form of a generator function. The generator function is in line 21, surrounded by round brackets (). If it was surrounded by square brackets, it would return a list. If you add the line print(type(res)) after line 40, you will see that res is indeed a generator object. The StopIterator error is avoided by using the for each loop. It will automatically stop as soon as it gets to the last object.
22nd Jul 2018, 9:57 AM
Anna
Anna - avatar
+ 3
Schindlabua Thank you. I'm afraid you're right and there's no "nice" way to check if any output is generated. Converting the output into a list seems to ruin the advantages of the generator though 🤔
22nd Jul 2018, 9:59 AM
Anna
Anna - avatar
+ 2
Generators are used so you can compute results lazily, that means if your generator returns 100 things you can stop after 50 and you won't waste any processing power on the other 50 as they are simply not computed. To know whether a generator will return anything at all, you will have to let the generator run to completion in the worst case; so there's not really a "nice" way to do what you want to do. You can convert the generator to a list though and work with that if you wish. mylist = list(res)
22nd Jul 2018, 9:37 AM
Schindlabua
Schindlabua - avatar
+ 2
If you are going to use the whole list later on anyway it's alright :P
22nd Jul 2018, 10:09 AM
Schindlabua
Schindlabua - avatar
+ 1
Anna so you have used generator expression to create generator then it's ok.
22nd Jul 2018, 11:20 AM
$¢𝐎₹𝔭!𝐨𝓝
$¢𝐎₹𝔭!𝐨𝓝 - avatar
+ 1
Kishalaya Saha usually you loop throgh the generator with a for loop.
22nd Jul 2018, 12:52 PM
Schindlabua
Schindlabua - avatar
0
I did not found yield in your code. I think for generator yield is necessary. also when generator iter goes out of bound it will throw the StopIteration exception and you have to handle that. if you don't want to handle exception than you can pass default argument with you next API call and check for the default value using while loop.
22nd Jul 2018, 9:29 AM
$¢𝐎₹𝔭!𝐨𝓝
$¢𝐎₹𝔭!𝐨𝓝 - avatar
0
Schindlabua What if I only need them one at a time, and want to save space?
22nd Jul 2018, 10:15 AM
Kishalaya Saha
Kishalaya Saha - avatar