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
Любая функция в 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)) # выведет 21
Добавьте 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
- методы
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
и как исправить мою функцию?
- питон
- функция
- рекурсия
- возврат
Он возвращает 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, я не знаю, с чего начать отладку. Существуют ли какие-либо общие проблемы, которые могут вызвать это?
- питон
- возврат
Вот что происходит:
- Вы вызываете процесс
(my_start_list)
. - В функции
если 9Блок 0026 выполняется, если
len(my_list) > 1
и там нет оператора возврата. Теперь, посколькуelse
не был выполнен, и поскольку это единственное место, где у вас есть предложение возврата, вы возвращаете значение по умолчанию, которое равноNone
. - Если в вашем списке 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: вернуть мой_список
Я думаю, что это немного проясняет намерение, а также позволяет избежать некоторых ловушек, связанных с хвостовой рекурсией.