python — Почему из функции возвращается None

Вопрос задан

Изменён 10 месяцев назад

Просмотрен 5k раз

Изучаю Python3. Реализовал рекурсивный алгоритм Евклида для поиска наибольшего общего делителя. Никак не пойму, почему функция возвращает None. Что самое интересное — строка print(b) выводит правильный результат и далее функция завершается, но результат None

def nod(a, b):
    if a == 0:
        print(b)
        return b
    elif b == 0:
        return a
    elif a > b:
        nod(a % b, b)
    else:
        nod(a, b % a)
  • python
  • python-faq
1

Любая функция в Python возвращает значение.

Если вы не используете инструкцию return явно, то функция возвращает None.

В вашем случае ветки условия elif a > b и else не возвращают ничего. Отсюда и берется None.

А вот и пример правильного, работоспособного кода (без лишнего вызова print):

def nod(a, b):
    if a == 0:
        return b
    elif b == 0:
        return a
    elif a > b:
        return nod(a % b, b)
    else:
        return nod(a, b % a)
print(nod(10, 2)) # выведет 2
1

Добавьте return в elif a > b: и else:

def nod(a, b):
    if a == 0:
        print(b)
        return b
    elif b == 0:
        return a
    elif a > b:
        return nod(a % b, b)
    else:
        return nod(a, b % a)

Зарегистрируйтесь или войдите

Регистрация через Google

Регистрация через Facebook

Регистрация через почту

Отправить без регистрации

Почта

Необходима, но никому не показывается

Отправить без регистрации

Почта

Необходима, но никому не показывается

Нажимая на кнопку «Отправить ответ», вы соглашаетесь с нашими пользовательским соглашением, политикой конфиденциальности и политикой о куки

python — Откуда None в выводе ? Глупый вопрос

Вопрос задан

Изменён 5 лет 4 месяца назад

Просмотрен 8k раза

Вот собственно сам код программы :

import time
class TestClass(object):
    """docstring for . """
    def __init__(self, name, yearofbirth, mounthofbith, dayofbith):
        super(TestClass, self).__init__()
        self.fname = name
        self.born = yearofbirth
        self.born1 = mounthofbith
        self.born2 = dayofbith
    def vozrast(self):
        self.year = int(time.strftime('%Y'))
        self.mounth= int(time.strftime('%m'))
        self.day = int(time.strftime('%d'))
        if (self.mounth >= self.born1):
            if(self.day >= self.born2):
                self.age = self.year - self.born
        else:
            self.age = int(self.year) - self.born - 1
        self.ret = self.age
        return self.ret
    def bio(self):
        self.old = self.vozrast()
        print(self.fname, self.old)
Ivan = TestClass('Ivan', 1999, 7, 2)
Sasha = TestClass('Sasha', 1976, 7 , 14)
print(Ivan.bio())
print(Sasha.bio())

Вывод:

('Ivan', 18)
None
('Sasha', 41)
None
[Finished in 0.027s]

Откуда «None» и как убрать ?

  • python
  • ооп
  • python-3. 5
  • print
  • методы
6

def bio(self):
    self.old = self.vozrast()
    print(self.fname, self.old)

В этом методе нет команды return, и так она возвращает значение None.

Вы вероятно хотели

def bio(self):
    self.old = self.vozrast()
    return (self.fname, self.old)

или — более просто —

def bio(self):
    return self.fname, self.vozrast()

Зарегистрируйтесь или войдите

Регистрация через Google

Регистрация через Facebook

Регистрация через почту

Отправить без регистрации

Почта

Необходима, но никому не показывается

Отправить без регистрации

Почта

Необходима, но никому не показывается

Нажимая на кнопку «Отправить ответ», вы соглашаетесь с нашими пользовательским соглашением, политикой конфиденциальности и политикой о куки

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

Задавать вопрос

спросил

Изменено 25 дней назад

Просмотрено 127 тысяч раз

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

 по умолчанию get_input():
    my_var = input('Введите "a" или "b": ')
    если my_var != "a" и my_var != "b":
        print('Вы не набрали "a" или "b".  Попробуйте еще раз.')
        получить_ввод()
    еще:
        вернуть my_var
print('получил ввод:', get_input())
 

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

 Введите "a" или "b": a
получил ввод: а
 

Но если я наберу что-то еще, а затем «a» или «b», я получу следующее:

 Введите "a" или "b": фиолетовый
Вы не набрали "а" или "б". Попробуйте еще раз.
Введите «а» или «б»: а
получил ввод: нет
 

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

  • питон
  • функция
  • рекурсия
  • возврат
5

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

 if my_var != "a" и my_var != "b":
    print('Вы не набрали "a" или "b". Попробуйте еще раз.')
    получить_ввод()
 

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

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

 >>> def f(x):
...     проходить
>>> напечатать(f(20))
Никто
 

Итак, вместо простого вызова get_input() в операторе if вам нужно вернуть что возвращает рекурсивный вызов:

 если my_var != "a" и my_var != "b":
    print('Вы не набрали "a" или "b". Попробуйте еще раз.')
    вернуть get_input()
 
7

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

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

1

 по определению get_input():
    my_var = input('Введите "a" или "b": ')
    если my_var != "a" и my_var != "b":
        print('Вы не набрали "a" или "b".
Попробуйте еще раз.') вернуть get_input() еще: вернуть my_var print('получил ввод:', get_input())

Я думаю, чтобы лучше понять, что на самом деле происходит в вашей рекурсивной функции, вы должны попытаться отладить свой код. Есть интересный инструмент визуализации выполнения кода, который я рекомендую, под названием Python Turor.

Я попробую этот тест на вашей рекурсивной функции и визуализирую процесс выполнения:

Сначала введите my_var как x , затем введите my_var как a .

В визуализаторе отладки видно, что когда my_var = a , он выполнит оператор возврата.

Затем рекурсивная функция вернет входное значение a в этой строке кода рекурсивной функции.

После этого он снова перейдет к выполнению функции get_input() , которая не возвращает никакого значения, поэтому окончательное значение print('got input:', get_input()) равно Нет .

Если вы замените вызов get_input() внутри рекурсивной функции на , верните get_input() Он вернет значение my_var , которое в этом тестовом примере равно и .

Надеюсь, эта демонстрация использует Инструмент визуализации отладки Python Tutor может помочь прояснить процесс выполнения рекурсивной функции.

python — функция всегда возвращает None

спросил

Изменено 9 месяцев назад

Просмотрено 23 тысячи раз

У меня есть код Python, который в основном выглядит так:

 мой_начальный_список = ...
процесс определения ( my_list ):
    #сделай что-нибудь
    
    если len(my_list) > 1:
        процесс (мой_список)
    еще:
        распечатать (мой_список)
        вернуть мой_список
   
печать (процесс (my_start_list))
 

Странная вещь: print(my_list) выводит правильное содержимое. Однако второй оператор печати, печатающий возвращаемое значение функции, всегда печатает None . Даже если я заменю обычный оператор return на return("abc") это все еще Нет .

Поскольку содержимое переменной кажется правильным за одну строку до оператора return, я не знаю, с чего начать отладку. Существуют ли какие-либо общие проблемы, которые могут вызвать это?

  • питон
  • возврат
5

Вот что происходит:

  1. Вы вызываете процесс (my_start_list) .
  2. В функции если 9Блок 0026 выполняется, если len(my_list) > 1 и там нет оператора возврата. Теперь, поскольку else не был выполнен, и поскольку это единственное место, где у вас есть предложение возврата, вы возвращаете значение по умолчанию, которое равно None .
  3. Если в вашем списке 0 или 1 элемент, вы возвращаете этот список.

Чтобы исправить это, вы хотите вернуть список, возвращенный process(my_list) .

То есть:

 процесс определения (my_list):
    # сделай что-нибудь
    ...
    если len(my_list) > 1:
        процесс возврата (my_list)
    еще:
        распечатать (мой_список)
        вернуть мой_список
 

Вы возвращаете список только тогда, когда в нем есть 1 или 0 элементов (базовый случай). Вам также нужен оператор return в первом блоке, где вы делаете рекурсивный вызов, или же вы переходите к базовому варианту, возвращаете список длины 1 на следующий уровень, а затем возвращаете None остальную часть вверх. Вместо этого то, что вы хотите, выглядит так:

 def process(my_list):
    # Сделай что-нибудь.
    если len(my_list) > 1:
        return process(my_list) #Если вы не возвращаете этот результат, вы возвращаете None
    еще:
        распечатать (мой_список)
        вернуть мой_список
 

Теперь каждый случай (не только базовый случай) имеет возвращаемое значение, так что возвращаемое значение будет распространяться вплоть до вашего первоначального вызова.

3

Вы вызываете процесс рекурсивно, но никогда не игнорируете его возвращаемое значение, когда делаете это. Добавьте оператор return в передайте возвращаемое значение ::

 def process ( my_list ):
    #сделай что-нибудь
    если len(my_list) > 1:
        процесс возврата (my_list)
    еще:
        распечатать (мой_список)
        вернуть мой_список
 

Теперь, когда len(my_list) > 1 равно True , вы фактически передаете возвращаемое значение рекурсивного вызова.

Как указывали другие, вам не хватает оператора return .

Лично я бы превратил эту хвостовую рекурсию в итерацию:

 def process(my_list):
    пока верно:
        # сделай что-нибудь
        если len(my_list) <= 1:
            вернуть мой_список
 

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