509 votes

Python: return, return None, and no return at all -- is there any difference?

Considérez ces trois fonctions :

def my_func1():
  print "Hello World"
  return None

def my_func2():
  print "Hello World"
  return

def my_func3():
  print "Hello World"

Ils semblent tous retourner None. Y a-t-il des différences entre le comportement de la valeur retournée par ces fonctions ? Y a-t-il des raisons de préférer l'une à l'autre ?


Voir aussi : <a href="https://stackoverflow.com/questions/10067013">est-il possible de ne rien retourner d'une fonction en python ?</a>

57 votes

Notez qu'il y a une différence stylistique. return None implique pour moi que la fonction a parfois une valeur de retour non-None, mais à l'endroit de return None, il n'y a pas de telle valeur de retour. Ne pas écrire de return du tout implique pour moi qu'il n'y a jamais de valeur de retour intéressante, un peu comme une "procédure" par opposition à une "fonction". return implique qu'il existe un retour précoce d'une "procédure" selon le point précédent.

770voto

Sur le comportement actuel, il n'y a pas de différence. Ils renvoient tous None et c'est tout. Cependant, il y a un moment et un endroit pour chacun de ces cas. Les instructions suivantes expliquent essentiellement comment les différentes méthodes doivent être utilisées (ou du moins comment j'ai appris qu'elles devraient l'être), mais ce ne sont pas des règles absolues, donc vous pouvez les mélanger si vous le jugez nécessaire.

Utilisation de return None

Cela indique que la fonction est effectivement censée renvoyer une valeur pour une utilisation ultérieure, et dans ce cas elle renvoie None. Cette valeur None peut ensuite être utilisée ailleurs. return None n'est jamais utilisé s'il n'y a pas d'autres valeurs de retour possibles de la fonction.

Dans l'exemple suivant, nous renvoyons la mère de la personne si la personne donnée est humaine. Si ce n'est pas une humaine, nous renvoyons None car la personne n'a pas de mère (supposons qu'elle n'est pas un animal ou quelque chose du genre).

def get_mother(person):
    if is_human(person):
        return person.mother
    else:
        return None

Utilisation de return

Ceci est utilisé pour la même raison que break dans les boucles. La valeur de retour n'a pas d'importance et vous voulez simplement sortir de toute la fonction. C'est extrêmement utile à certains endroits, même si vous n'en avez pas souvent besoin.

Nous avons 15 prisonniers et nous savons que l'un d'eux a un couteau. Nous parcourons chaque prisonnier un par un pour vérifier s'ils ont un couteau. Si nous tombons sur la personne avec le couteau, nous pouvons simplement quitter la fonction car nous savons qu'il n'y a qu'un couteau et aucune raison de vérifier le reste des prisonniers. Si nous ne trouvons pas le prisonnier avec le couteau, nous lançons une alerte. Cela pourrait être fait de nombreuses manières différentes et utiliser return n'est probablement même pas la meilleure façon, mais c'est juste un exemple pour montrer comment utiliser return pour sortir d'une fonction.

def find_prisoner_with_knife(prisoners):
    for prisoner in prisoners:
        if "knife" in prisoner.items:
            prisoner.move_to_inquisition()
            return # pas besoin de vérifier le reste des prisonniers ni de lancer une alerte
    raise_alert()

Remarque : Vous ne devriez jamais faire var = find_prisoner_with_knife(), car la valeur de retour n'est pas censée être récupérée.

Ne pas utiliser return du tout

Cela renverra également None, mais cette valeur n'est pas censée être utilisée ou récupérée. Cela signifie simplement que la fonction s'est terminée avec succès. C'est essentiellement la même chose que return dans les fonctions void dans des langages tels que C++ ou Java.

Dans l'exemple suivant, nous définissons le nom de la mère de la personne, puis la fonction se termine après avoir réussi.

def set_mother(person, mother):
    if is_human(person):
        person.mother = mother

Remarque : Vous ne devriez jamais faire var = set_mother(my_person, my_mother), car la valeur de retour n'est pas censée être récupérée.

45voto

David Marx Points 2393

Oui, ils sont tous les mêmes.

Nous pouvons examiner le code machine interprété pour confirmer qu'ils font exactement la même chose.

import dis

def f1():
  print "Hello World"
  return None

def f2():
  print "Hello World"
  return

def f3():
  print "Hello World"

dis.dis(f1)
    4   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    5   5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f2)
    9   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    10  5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f3)
    14  0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE            
        5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

7 votes

Faites attention ici... dis.dis renvoie None :-X

0 votes

La seule façon d'obtenir la sortie de cela en tant que chaîne est de rediriger stdout vers un type de tampon IO (par exemple, StringIO). Même alors, comparer directement comme ça pourrait ne pas fonctionner car je crois que dis.dis signale également certains numéros de ligne ...

0 votes

Il est sans importance qu'ils utilisent ou non les mêmes registres exacts de toute façon, donc j'ai modifié mon code pour que nous regardions simplement le code machine maintenant au lieu de faire une sorte de comparaison de chaîne loufoque. Merci pour la mise en garde très importante.

33voto

Fabiano Points 43

Comme d'autres l'ont déjà répondu, le résultat est exactement le même, None est retourné dans tous les cas.

La différence est stylistique, mais veuillez noter que PEP8 exige que l'utilisation soit cohérente :

Soyez cohérent dans les instructions de retour. Toutes les instructions de retour dans une fonction devraient soit retourner une expression, soit aucune d'entre elles ne devraient. Si une quelconque instruction de retour renvoie une expression, toutes les instructions de retour où aucune valeur n'est renvoyée devraient explicitement indiquer ceci comme return None, et une instruction de retour explicite devrait être présente à la fin de la fonction (si atteignable).

Oui :

def foo(x):
    if x >= 0:
        return math.sqrt(x)
    return None

def bar(x):
    if x < 0:
        return None
    return math.sqrt(x)

Non :

def foo(x):
    if x >= 0:
        return math.sqrt(x)

def bar(x):
    if x < 0:
        return
    return math.sqrt(x)

https://www.python.org/dev/peps/pep-0008/#programming-recommendations


Fondamentalement, si vous renvoyez jamais une valeur non-None dans une fonction, cela signifie que la valeur de retour a une signification et est destinée à être capturée par les appelants. Donc, lorsque vous retournez None, cela doit aussi être explicite, pour indiquer que None dans ce cas a une signification, c'est l'une des valeurs de retour possibles.

Si vous n'avez pas besoin de retourner du tout, votre fonction fonctionne essentiellement comme une procédure au lieu d'une fonction, alors il vous suffit de ne pas inclure l'instruction return.

Si vous rédigez une fonction de type procédure et qu'il y a une opportunité de retourner plus tôt (c'est-à-dire que vous avez déjà terminé à ce moment-là et n'avez pas besoin d'exécuter le reste de la fonction), vous pouvez utiliser des retours vides pour signaler au lecteur qu'il s'agit simplement d'une fin d'exécution anticipée et que la valeur None retournée implicitement n'a aucune signification et n'est pas destinée à être capturée (la fonction de type procédure renvoie toujours None de toute façon).

23voto

mgilson Points 92954

Chacun renvoie le même singleton None -- Il n'y a pas de différence fonctionnelle.

Je pense qu'il est raisonnablement idiomatique de laisser de côté l'instruction return sauf si vous en avez besoin pour sortir de la fonction plus tôt (dans ce cas, un simple return est plus courant), ou retourner quelque chose d'autre que None. Il est également logique et semble idiomatique d'écrire return None lorsqu'il s'agit d'une fonction qui a une autre voie qui renvoie quelque chose d'autre que None. Écrire return None explicitement est un indice visuel pour le lecteur qu'il y a une autre branche qui renvoie quelque chose de plus intéressant (et que le code appelant devra probablement gérer les deux types de valeurs de retour).

Souvent en Python, les fonctions qui renvoient None sont utilisées comme des fonctions void en C -- Leur but est généralement d'opérer sur les arguments d'entrée sur place (à moins que vous n'utilisiez des données globales (frissons)). Renvoyer None rend généralement plus explicite que les arguments ont été modifiés. Cela rend un peu plus clair pourquoi il est logique de laisser de côté l'instruction return d'un point de vue des "conventions du langage".

Cela dit, si vous travaillez dans une base de code qui a déjà des conventions prédéfinies à ce sujet, je suivrais certainement la même voie pour aider à maintenir l'uniformité de la base de code...

1 votes

Ou plus généralement, n'importe quelles fois qu'une fonction se termine sans atteindre une instruction de return, elle retourne None.

0 votes

Il n'est pas idiomatique d'omettre l'instruction return si la fonction est censée renvoyer une valeur. Seules les fonctions qui fonctionnent uniquement à travers des effets secondaires doivent omettre l'instruction return.

0 votes

@molecule - Oui, je pense que peut-être je n'ai pas fait du bon travail dans mon explication ici. J'ai essayé de la mettre à jour sans en faire un copié-collé de la réponse (beaucoup meilleure) ci-dessus. Je ne suis toujours pas super satisfait de ce post... Une partie de moi veut le supprimer (car la réponse ci-dessus est tellement meilleure) et une partie de moi veut le garder - 9 personnes jusqu'à présent ont pensé que c'était bien pour une raison ou une autre. Peut-être que j'ai touché quelque chose que quelqu'un d'autre a raté?

6voto

Yehuda Schwartz Points 1211

En termes de fonctionnalité, ils sont tous les mêmes, la différence entre eux réside dans la lisibilité du code et le style (ce qui est également important à considérer)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X