The code below is based on this recipe. However, the key point of the recipe - that it provides a way to break out of the iteration on an iterator if the iterator is empty - doesn't seem to work here, instead behaving in the following undesired ways:
How can I ensure that:
Here's the code:
def my_func(choice_pattern, input):
# Search in input for some things to choose from.
choice_iterator = choice_pattern.finditer(input, re.M)
if not choice_iterator:
print "No choices. Exiting..."
sys.exit()
else:
# Show choices to the user. For each one, ask user for a yes/no response. If
# choice accepted, return a result. Otherwise show user next choice. If no
# choices accepted by user, quit.
for choice in choice_iterator:
print choice.group()
# get_yes_no_answer() returns True or False depending on user response.
if get_yes_no_answer():
return choice
else:
# Check if iterator is empty. If so, quit; if not, do something else.
try:
next_choice = choice_iterator.next()
except StopIteration:
print "No matches. Exiting..."
sys.exit()
else:
choice_iterator = itertools.chain([next_choice], choice_iterator)
why are you doing it this way at all? why not just:
def get_choice(pattern, inpt):
choices = pattern.finditer(inpt, re.M)
if not choices:
sys.exit('No choices')
for choice in choices:
print(choice.group(0))
if get_yes_no_answer():
return choice
sys.exit('No matches')
I don't know what your is the length of your input but I doubt it's worth the trouble.
You don't need to check if the iterator is empty. The for loop will do that for you, and stop when the iterator is empty. It's as simple as that.
Also, you don't need the else after the sys.exit() or the return.
That done, your code looks like this:
def my_func(choice_pattern, input):
# Search in input for some things to choose from.
choice_iterator = choice_pattern.finditer(input, re.M)
if not choice_iterator:
print "No choices. Exiting..."
sys.exit()
# Show choices to the user. For each one, ask user for a yes/no response. If
# choice accepted, return a result. Otherwise show user next choice. If no
# choices accepted by user, quit.
for choice in choice_iterator:
print choice
# get_yes_no_answer() returns True or False depending on user response.
if get_yes_no_answer():
return choice
# Loop exited without matches.
print "No matches. Exiting..."
sys.exit()
That's it!
What happens is that you in the loop, also gets the next item. The result is that you in fact only show every second answer.
In fact, you can simplify it even more:
def my_func(choice_pattern, input):
choice_iterator = choice_pattern.finditer(input, re.M)
if choice_iterator:
for choice in choice_iterator:
print choice
if get_yes_no_answer():
return choice
# If there is no choices or no matches, you end up here:
print "No matches. Exiting..."
sys.exit()
Iterators are used pretty much as any sequence type. You don't need to treat it differently from a list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With