Invoque test(45)
. Esto prueba si 45 > 9
, que es verdadero, por lo que invoca test(35)
(45 - 10), sin devolver su resultado. Lo mismo ocurre con test(25)
y test(15)
, hasta que finalmente se invoca test(5)
.
Esto imprime 'valor real 5', y luego devuelve 5. Pero devolver un resultado de una función siempre lo devuelve a la persona que llama directamente a esta función. No salta inmediatamente a través de varias llamadas; después de todo, la persona que llama puede querer hacer algo con el resultado devuelto antes de devolver algo al es llamador. Sin embargo, en este caso, solo test(5)
devuelve algo; todos los demás llaman al test(x - 10)
, espere a que vuelva, ignore lo que devuelva, y luego (implícitamente) devuelva None
. Dado que la invocación más externa test(45)
es uno de estos casos, lo que obtienes es None
.
He aquí un intento de una visualización de lo que sucede:
test(45):
| test(35):
| | test(25):
| | | test(15):
| | | | test(5):
| | | | | print('real value',5)
| | | | | return 5 to test(15)
| | | | return None to test(25)
| | | return None to test(35)
| | return None to test(45)
| return None
no llamó test(5)
en el intérprete, test(5)
fue llamado desde dentro de otra llamada a la función. Entonces el retorno de test(5)
va a que llama a la función. El hecho de que se trate de una función que se llama a sí misma es completamente irrelevante. Te obtener exactamente los mismos resultados si su código se veía así:
def test45(x):
if x > 9 :
test35(x - 10)
else:
print('real value',x)
return x
def test35(x):
if x > 9 :
test25(x - 10)
else:
print('real value',x)
return x
def test25(x):
if x > 9 :
test15(x - 10)
else:
print('real value',x)
return x
def test15(x):
if x > 9 :
test5(x - 10)
else:
print('real value',x)
return x
def test5(x):
if x > 9 :
print 'No more tests :('
else:
print('real value',x)
return x
La prueba (x) se llama a la función con 'x = 45' es igual que llamar test45(45)
. Espero que pueda ver por qué es obvio que None
debe devolverse cuando la recursión no esté involucrada en. Bueno, cuando se trata de recursividad, nada cambia. La instrucción return
no sabe ni le importa si regresa de una función invocada recursivamente, se comporta exactamente de la misma manera en cualquier caso.
De hecho, la recursividad no es nada "especial" en absoluto; se comporta exactamente de la misma manera que las llamadas a funciones ordinarias. Recibe información de lo que lo llamó por medio de argumentos, y devuelve información a la cosa que lo llamó al regresar. Si no devuelve algo (quizás solo en un brazo de un if
), se devolverá None
a su interlocutor, independientemente de si llama a cualquier otra función en esa rama, independientemente de lo que pueda devolver esa función si llama algo, e independientemente de si la función que llamas pasa a ser la misma función en la que estás dentro.
Es exactamente lo mismo que con una llamada no recursiva: si desea propagar el valor de retorno de la función que llamó, debe hacerlo usted mismo, con la palabra clave 'return'. Llamar a una función produce su valor de retorno, pero depende de usted hacer algo con ese valor de retorno, ya sea que la función llamada sea recursiva o no. –