2013-04-03 4 views
6

J'ai un code Python qui ressemble fondamentalement ceci:Python: Fonction retourne toujours Aucun

my_start_list = ... 

def process (my_list): 
    #do some stuff 

    if len(my_list) > 1: 
     process(my_list) 
    else: 
     print(my_list) 
     return my_list 

print(process(my_start_list)) 

La chose étrange est: impression (my_list) imprime le contenu approprié. Cependant, la deuxième instruction d'impression qui imprime la valeur de retour de la fonction imprime toujours "Aucun". Même si je remplace l'instruction de retour normale par return ("abc") il est toujours None.

Comme le contenu de la variable semble être correct une ligne avant l'instruction return, je ne sais pas par où débuter le débogage. Y at-il des problèmes communs qui peuvent causer cela?

+10

utilisez 'return process (my_list)' lors de l'appel récursif. –

+4

@ NPE Je suppose que '#do stuff 'comprend la modification de la liste d'une manière ou d'une autre; sinon tu as raison; ceci devrait se répéter indéfiniment. –

+1

related: http://stackoverflow.com/questions/11097822/weird-function-return-value –

Répondre

8

Voici ce qui se passe:

  1. Vous appelez process(my_start_list).
  2. Dans la fonction, le bloc if est exécuté si len(my_list) > 1 et il n'y a pas d'instruction de retour.
    Ici, puisque le else n'a pas été exécuté et puisque c'est le seul endroit où vous avez la clause de retour, vous renvoyez la valeur par défaut qui est None.
  3. Si vous avez 0 ou 1 éléments dans votre liste, vous renvoyez cette liste.

Alors, retourner la liste retournée par process(my_list)
C'est:

def process(my_list): 
    #do some stuff 
    ... 
    if len(my_list) > 1: 
     return process(my_list) 
    else: 
     print(my_list) 
     return my_list 
10

Vous ne renvoyez la liste que si vous avez 1 ou 0 éléments (le cas de base). Vous avez également besoin d'une instruction return dans le premier bloc, où vous effectuez l'appel récursif, ou bien vous accédez au cas de base, renvoyez la liste length-1 au niveau suivant, puis renvoyez None jusqu'au bout. . Donc ce que vous voulez ressemble à ceci, à la place:

def process(my_list): 
    # Do some stuff. 
    if len(my_list) > 1: 
     return process(my_list) #If you don't return this result, you return None 
    else: 
     print(my_list) 
     return my_list 

Maintenant tous les cas (pas seulement le cas de base) a une valeur de retour, de sorte que la valeur de retour se propage tout le chemin du retour jusqu'à l'appel initial.

+0

Vrai, mais un seul point de sortie (retour) est toujours meilleur. –

+0

Sa fonction est récursive; il va se retrouver avec au moins deux déclarations de retour, peu importe ce qu'il fait (un pour le scénario de base et un pour l'appel récursif). –

+4

@marksweb: ** Pourquoi ** un single reviendrait-il mieux? Cela a été discuté à la mort, mais ce n'est plus vrai. Voir [Une fonction devrait-elle avoir une seule déclaration de retour?] (Http://stackoverflow.com/q/36707) –

3

Vous appelez process récursivement mais n'ignorez jamais sa valeur de retour lorsque vous le faites. Ajoutez une instruction return-passe sur la valeur de retour ::

def process (my_list): 
    #do some stuff 

    if len(my_list) > 1: 
     return process(my_list) 
    else: 
     print(my_list) 
     return my_list 

Maintenant, quand len(my_list) > 1 est True, vous passez en fait sur la valeur de retour de l'appel récursif.

2

Comme d'autres l'ont souligné, il vous manque une déclaration return.

Personnellement, je transformer cette récursivité en queue itération:

def process(my_list): 
    while True: 
     # do some stuff 
     if len(my_list) <= 1: 
      return my_list 

Je pense que cela rend l'intention un peu plus clair, et évite aussi des pitfalls associated with tail recursion.

Questions connexes