Парадокс рекурсивной функции в Python.. как это можно объяснить?
Я сделал очень простую функцию, которая берет список чисел и возвращает список чисел, округленный до нескольких цифр:
def rounded(lista, digits = 3):
neulist = []
for i in lista:
neulist.append(round(i, digits))
return neulist
Однако я по ошибке поместил саму функцию в код вместо встроенной round()
(как в примере ниже):
def rounded(lista, digits = 3):
neulist = []
for i in lista:
neulist.append(rounded(i, digits))
return neulist
и получил этот вывод:
Traceback (most recent call last):
File "<pyshell#286>", line 1, in <module>
rounded(a)
File "<pyshell#284>", line 4, in rounded
neulist.append(rounded(i, digits))
File "<pyshell#284>", line 3, in rounded
for i in lista:
TypeError: 'float' object is not iterable
Вопрос в том, как интерпретатор узнает, что ему пришлось применить функцию. rounded()
при оценке функции rounded()
сам? Как это может быть так или иначе сейчас rounded()
Является ли функция с плавающей точкой, если она пытается интерпретировать эту функцию? Существует ли своего рода процедура с двумя циклами для оценки и интерпретации функций? Или я что-то здесь не так?
3 ответа
Функция является объектом. Он создается при определении, а не при его вызове, поэтому, если бы Python не знал, как его использовать, он вызвал бы ошибку до того, как был сделан любой вызов.
Однако вы назвали это списком. Во время итерации функция вызывается рекурсивно с первым элементом списка - предположительно, с плавающей точкой. С этим поплавком в качестве аргумента, for i in lista:
больше не имеет смысла, и у вас есть ошибка.
Вы только что наткнулись на рекурсию.
Рекурсивные функции очень распространены в программировании. Рассмотрим следующую (наивную) функцию для вычисления n
число Фиббоначи:
def fib(x):
if x<=2:
return 1
else:
return fib(x-1)+fib(x-2)
Функция знает, что она вызывает сама себя, потому что определение функции отмечается, как только интерпретатор достигает fib(x):
, С этого момента, fib
определено. В частности, для python, поскольку это динамически типизированный язык, нет разницы, если вы вызываете функцию с целым числом, строкой или с плавающей точкой - все, что имеет значение, - это то, что функция принимает ровно один аргумент.
Здесь действительно происходят два процесса. Функция компилируется в том виде, в котором она встречается в исходном тексте, после чего к ней делается вызов. Тело функции включает в себя вызов rounded
, но это на самом деле отслеживается как имя функции. Проверь это:
def fun1(x):
if x == 0:
print x
else:
fun1(x-1)
fun2 = fun1
def fun1(x):
print x
fun2(3)
Здесь мы определяем fun1()
с явно рекурсивным призывом к себе. Однако после переопределения fun1()
вызов в первом определении функции теперь полностью относится к другой функции.