If you do this more often and the objective is less code and you don't mind it getting slower, you could use a decorator that wraps your generator in another that asserts the given check afterwards:
@assert_afterwards(list_check=lambda yielded: len(yielded) > 0)
def random_select(iterations):
for index in range(iterations):
if random.randint(0, 9) > 4:
yield index
Though for checking len > 0
, you wouldn't need to keep track of all yielded values but just of their count or even just of whether there were any yields:
@assert_afterwards(count_check=lambda yielded: yielded > 0)
def random_select(iterations):
for index in range(iterations):
if random.randint(0, 9) > 4:
yield index
@assert_afterwards(any_check=True)
def random_select(iterations):
for index in range(iterations):
if random.randint(0, 9) > 4:
yield index
Possible implementation of that decorator (could be improved with better messages for failed assertions and at least the "any" version could be made much faster), including demo:
import random
random.seed(0)
def assert_afterwards(any_check=None, count_check=None, list_check=None):
def deco(gen):
if any_check:
def gen_any(*args):
yielded = False
for value in gen(*args):
yield value
yielded = True
assert yielded
return gen_any
if count_check:
def gen_count(*args):
yielded = 0
for value in gen(*args):
yield value
yielded += 1
assert count_check(yielded)
return gen_count
def gen_list(*args):
yielded = []
for value in gen(*args):
yield value
yielded.append(value)
assert list_check(yielded)
return gen_list
return deco
#@assert_afterwards(list_check=lambda yielded: len(yielded) > 0)
#@assert_afterwards(count_check=lambda yielded: yielded > 0)
@assert_afterwards(any_check=True)
def random_select(iterations):
for index in range(iterations):
if random.randint(0, 9) > 4:
yield index
for _ in range(100):
for x in random_select(5):
print(x, flush=True, end=' ')
print()
Try it online!