Рекурсивный вызов функции и/или цикл повторяются не так, как ожидалось

Эта функция должна давать ответы на вводимые пользователем вопросы для списка действий и соответствующего списка вариантов. Он возвращает список логических значений. Например. ['смотреть', 'играть', ...] и ['футбол', 'спорт', ...] => Ты смотришь футбол? _ так далее.

Проблема:

Функция повторяется слишком часто, когда пользователь вводит неверные данные, хотя, как видите, они обрабатываются отдельно!

Я определил, что со списками из одного элемента этот код работает нормально. Итак, вот мой код. Я знаю отладку печати, и я чертовски новичок.

def yes_or_no(action, choices, *argv):
    decisions = []
    #remember previous decisions (in case an error occured)
    for arg in argv:
        decisions = arg
    print('choices: ', choices)
    print('decisions: ', decisions)
    for choice in choices:
        print(choice)
        decision = input('Do you want to {} {}? Plase, type [y/n]: '.format(action, choice))
        try:
            decision = str(decision)
            if decision == 'y':
                decisions.append(True)
                pass
            elif decision == 'n':
                decisions.append(False)
                pass
            else:
                print('\nYour input was neither y = \'yes\' nor n = \'no\'.\nOnce again.')
                new_choices = choices[choices.index(choice):]
                yes_or_no(action, new_choices, decisions)
        except ValueError:
            print('\nYour input was neither y = \'yes\' nor n = \'no\'.\nOnce again.')
            new_choices = choices[choices.index(choice):]               
            yes_or_no(action, new_choices, decisions)
    print(decisions)
    return (decisions)

Ну, когда я впервые ввожу неверный ввод, начинается рекурсия, но for selection в вариантах повторяется 2(!) раза, хотя в этом списке всего один элемент!

Поэтому я добавил операторы print() в код, чтобы увидеть это — это безумие!

Вот мои результаты из командной строки:

choices:  ['football', 'sports']
decisions:  []
watch
Do you want to watch football? Plase, type [y/n]: sure

Your input was neither y = 'yes' nor n = 'no'.
Once again.
choices:  ['football', 'sports']
decisions:  []
football
Do you want to watch football? Plase, type [y/n]: n
sports
Do you want to watch sports? Plase, type [y/n]: y
sports
Do you want to watch sports? Plase, type [y/n]: y
[False, True, True]
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это потому, что вы продолжаете повторять choices, когда вы даете неправильный decision перед последним элементом choices. Решением здесь должно быть добавление оператора return после вызова функции. Ваш фрагмент, обновленный оператором, будет выглядеть так:

def yes_or_no(action, choices, *argv):
    decisions = []
    #remember previous decisions (in case an error occured)
    for arg in argv:
        decisions = arg
    print('choices: ', choices)
    print('decisions: ', decisions)
    for choice in choices:
        print(choice)
        decision = input('Do you want to {} {}? Plase, type [y/n]: '.format(action, choice))
        try:
            decision = str(decision)
            if decision == 'y':
                decisions.append(True)
                pass
            elif decision == 'n':
                decisions.append(False)
                pass
            else:
                print('\nYour input was neither y = \'yes\' nor n = \'no\'.\nOnce again.')
                new_choices = choices[choices.index(choice):]
                return yes_or_no(action, new_choices, decisions)
        except ValueError:
            print('\nYour input was neither y = \'yes\' nor n = \'no\'.\nOnce again.')
            new_choices = choices[choices.index(choice):]               
            return yes_or_no(action, new_choices, decisions)
    print(decisions)
    return (decisions)

Привет, это снова я - Я просто не мог снова войти в свою быстро созданную учетную запись с поддельной почтой :P

Я получил полезный ответ в течение нескольких минут, и поэтому я просто хотел поделиться своим окончательным решением этой рекурсии, которая обрабатывает вопросы «да или нет», которые генерируются двумя списками, переданными функции.

def yes_or_no(action, choices, *argv):

    error_message = '\nYour input was neither y = \'yes\' nor n = \'no\'.\nOnce again.\n'
    decisions = []

    #remember previous decisions (in case an error occured)
    for arg in argv:
        decisions = arg

    for choice in choices:
        decision = input('Do you want to {} {}? Plase, type [y/n]: '.format(action, choice))

        try:
            decision = str(decision)
            if decision == 'y':
                decisions.append(True)
            elif decision == 'n':
                decisions.append(False)
            else:
                print(error_message)
                decisions = yes_or_no(action, choices[choices.index(choice):], decisions)
                break
        except ValueError:
            print(error_message)
            decisions = yes_or_no(action, choices[choices.index(choice):], decisions)
            break

    return (decisions)

Резюме: Это решение мотивированной проблемы ("да или нет" - обработка вопросов), вероятно, не самое эффективное, но оно всеобъемлющее и легко применимо к любой проблеме такого рода. Как вы, возможно, заметили, я не использовал предложенный «возврат», так как «разрыв» вызывает тот же эффект, потому что есть только одна (!) циклическая рекурсия («для выбора в выборе:») для разрыва. Я предпочел «перерыв» «возврату», потому что я думаю, что это технически быстрее разрешается компилятором.

Недостаток: Пока только один недостаток пришел мне в голову. В случае большого количества неверных входных данных — под многими я имею в виду миллионы и более — этой рекурсии потребуется все больше и больше места для хранения. Но я думаю, это хорошо известно для рекурсий. ;-)

Другие вопросы по теме