Почему моя рекурсивная функция не возвращает ничего?

#python #printing #return

Вопрос:

У меня есть эта функция, которая вызывает саму себя:

 def get_input():
    my_var = input('Enter "a" or "b": ')

    if my_var != "a" and my_var != "b":
        print('You didn't type "a" or "b". Try again.')
        get_input()
    else:
        return my_var

print('got input:', get_input())
 

Теперь, если я введу только «a» или «b», все будет работать нормально:

 Type "a" or "b": a
got input: a
 

Но, если я наберу что-то еще, а затем «а» или «в», я получу это:

 Type "a" or "b": purple
You didn't type "a" or "b". Try again.
Type "a" or "b": a
got input: None
 

Я не знаю, почему get_input() возвращается None , так как он должен только возвращаться my_var . Откуда это None берется и как мне исправить свою функцию?

Комментарии:

1. Вам нужно сделать return Dat_Function() это при рекурсивном вызове.

2. Просто совет: идиоматическим способом этого my_var != "a" and my_var != "b" условия было бы my_var not in ('a', 'b')

3. @гонз не обязательно. Теперь вы попадаете в кучу, выделяя кортеж только для простого сравнения. Это может быть болезненно на критическом пути, и на самом деле это не намного более читабельно.

Ответ №1:

Он возвращается None , потому что, когда вы рекурсивно вызываете его:

 if my_var != "a" and my_var != "b":
    print('You didn't type "a" or "b". Try again.')
    get_input()
 

..вы не возвращаете значение.

Таким образом, пока рекурсия происходит, возвращаемое значение отбрасывается, и затем вы выпадаете из конца функции. Выпадение из конца функции означает , что python неявно возвращает None , точно так же, как это:

 >>> def f(x):
...     pass
>>> print(f(20))
None
 

Итак, вместо того, чтобы просто позвонить get_input() в свое if заявление, вам нужно return это:

 if my_var != "a" and my_var != "b":
    print('You didn't type "a" or "b". Try again.')
    return get_input()
 

Комментарии:

1. Не следует ли снова выполнить оператор if, если он вызывается рекурсивно? Я не понимаю, почему он не вернет значение.

2. Нет. Смотрите мою правку. Происходит рекурсия, а затем вы отбрасываете то, что возвращает рекурсия.

3. Ты потерял меня из-за этого main() кусочка… Вы можете терпеть неудачу столько раз, сколько захотите , тот, который «преуспеет», вернется my_var , который будет передан ( return ed) через все рекурсивные вызовы вплоть до исходного вызывающего абонента. Что, да, так и есть main() .

4. Используйте return для рекурсивной функции , чтобы поместить ее значение в стек, чтобы, когда функция будет выполнять рекурсию, значения из стека принимались одно за другим. Если вы не используете return , стек будет собирать только значения «Нет».

5. вы, сэр, гений! Это не было для меня интуитивно понятным.

Ответ №2:

Чтобы вернуть значение, отличное от None, вам необходимо использовать оператор return.

В вашем случае блок if выполняет возврат только при выполнении одной ветви. Либо переместите возврат за пределы блока if/else, либо используйте возврат в обоих вариантах.

Комментарии:

1. Я пытался убрать его из квартала, но безрезультатно. Вместо того, чтобы возвращать правильное значение, он возвращает первое неверное значение. Кроме того, мне не нужен оператор return для части if оператора if/else, потому что я хочу, чтобы функция возвращала только правильное значение.

Ответ №3:

 def get_input():
    my_var = input('Enter "a" or "b": ')

    if my_var != "a" and my_var != "b":
        print('You didn't type "a" or "b". Try again.')
        return get_input()
    else:
        return my_var

print('got input:', get_input())
 

Ответ №4:

я думаю, что этот код более понятен

 def get_input():
    my_var = str(input('Enter "a" or "b": '))
    if my_var == "a" or my_var == "b":
        print('got input:', my_var)
        return my_var
    else:
        print('You didn't type "a" or "b". Try again.')
        return get_input()
get_input()
 

Комментарии:

1. @SergeyShubin как вы думаете, чем этот код отличается от кода пользователя 6348168. Я чувствую, что и то, и другое-одно и то же.

2. @jiten код был изменен после моего комментария, поэтому он больше не актуален. Я думаю, что мне следует удалить его