Java >> Tutoriel Java >  >> Tag >> return

Pouvez-vous réellement renvoyer plusieurs valeurs à partir d'une fonction en Python ?

Alors que nous nous dirigeons vers l'été, j'ai trouvé un peu plus de temps pour écrire. En conséquence, j'ai eu un peu d'espace pour parler de certains sujets qui me préoccupent récemment. Par exemple, un a vu un tweet affirmant récemment que vous pouvez renvoyer plusieurs valeurs à partir d'une fonction en Python. Mais, pouvez-vous vraiment faire cela ? C'est le sujet de la pièce d'aujourd'hui.

Inspiration technique pour Twitter

J'ai récemment eu l'inspiration d'écrire ce post après avoir vu le tweet suivant flotter.

Des choses simples qui font une énorme différence.

En Python 🐍, vous pouvez renvoyer plusieurs valeurs à partir d'une fonction. pic.twitter.com/sfqmh5QRzJ

– Santiago (@svpino) 18 avril 2021

Au cas où ce tweet serait supprimé, l'essentiel est que "le gars de l'apprentissage automatique", Santiago, a partagé un tweet qui affirmait que vous pouviez renvoyer plusieurs valeurs à partir d'une fonction en Python. Voici son exemple :

def operations(x, y):
  return x + y, x * y

result1, result2 = operations(4, 4)
print(result1, result2)
# 8 16

Quand je l'ai vu, ma première pensée a été :"eh bien, vous ne pouvez pas réellement renvoyer plusieurs valeurs à partir d'une fonction en Python. " Ensuite, j'ai réalisé à quel point j'avais l'air d'un snob pédant, alors je n'ai pas pris la peine de commenter. Après tout, je ne pense pas que l'intention du message de Santiago soit de diffuser de fausses informations. En fait, si vous recherchez "retourner plusieurs valeurs python" sur Google, vous obtiendrez plusieurs solutions qui ressemblent à ce que Santiago a partagé.

Cela dit, j'adore enseigner, alors j'ai pensé que ce serait une excellente occasion de prendre cet extrait génial de Santiago et d'essayer d'y ajouter un peu de contexte. Sans plus tarder, plongeons !

Fonctionnement des fonctions

Dans les termes les plus génériques possibles, les fonctions Python prennent des entrées et produisent des sorties . Parfois, nous essayons d'utiliser une terminologie différente lorsque nous voulons être plus précis sur ce que fait une fonction. Par exemple, une définition stricte pour une fonction serait une unité de code qui prend une entrée et produit une sortie sans effets secondaires . Dans ce cas, les effets secondaires sont les modifications des entrées qui persistent après l'exécution de la fonction. En revanche, il y aurait une procédure qui prend une entrée et la modifie sans sortie.

Cela dit, je n'ai pas vraiment l'intention d'entrer dans toutes sortes de jargons liés aux fonctions. Si vous êtes intéressé par ce genre de chose, vous pouvez consulter mon article sur les différences entre les fonctions et les procédures. Au lieu de cela, je veux parler un peu de la façon dont les fonctions fonctionnent plus largement.

Pour commencer, reprenons l'exemple de Santiago :

def operations(x, y):
  return x + y, x * y

Ici, Santiago définit une fonction appelée "opérations". L'idée derrière cette fonction est assez simple :en fournissant deux nombres, vous pouvez obtenir le résultat de l'addition et de la multiplication de ces nombres en même temps.

Maintenant, Python peut être un peu frustrant car nous n'avons aucune idée de quels types de variables x et y sont censés être. Je savais seulement qu'il était censé accepter des nombres à cause de l'exemple fourni par Santiago, mais il peut y avoir d'autres entrées valides. Par exemple, je sais qu'il est possible de mettre à l'échelle une liste en utilisant un entier, et il est également possible d'ajouter deux listes. Cela dit, je ne peux pas penser à un exemple sur le dessus de ma tête qui fonctionnerait pour une paire d'entrées. Si je peux trouver quelque chose, je mettrai à jour ce post. Cela dit, sachez simplement que les programmes planteront souvent avec une TypeError si les types ne sont pas comme prévu.

Quoi qu'il en soit, en supposant que nous fournissions des entrées appropriées, les deux expressions sont ensuite évaluées. Par exemple, si nous appelons operations(10, 2) , nous pouvons nous attendre à ce que l'expression d'addition soit évaluée à 12 et l'expression de multiplication à être évaluée à 20. Après cela, le résultat est renvoyé à l'utilisateur.

Bien sûr, la question devient alors :à quoi ressemble le résultat renvoyé ? Nous allons jeter un œil dans la section suivante.

Valeurs de retour de la fonction

Python est un peu farfelu dans les types de valeurs qu'une fonction peut renvoyer. En d'autres termes, comme les fonctions n'ont pas de type de retour, elles peuvent tout retourner. En fait, une seule fonction n'a même pas besoin d'être cohérente dans les types de valeurs qu'elle renvoie :

def generate_chaos(x):
  if x == 0:
    return "Hola"
  elif x > 0:
    return 7
  else:
    return [2, 4, 6, 8]

Cependant, les fonctions doivent renvoyer quelque chose, même si ce quelque chose est implicitement rien (None ). Cela dit, bien que nous devions retourner quelque chose, cela ne peut être qu'un chose.

Mais attendez une minute ? Clairement, Santiago renvoie plus d'une chose, non ? Jetez à nouveau un coup d'œil à sa solution :

def operations(x, y):
  return x + y, x * y

result1, result2 = operations(4, 4)
print(result1, result2)
# 8 16

Il semble que cette virgule fournit en quelque sorte deux sorties, et nous devons utiliser cette même virgule pour enregistrer les deux sorties.

En réalité, il y a un peu de magie qui se passe ici dans les coulisses. Il existe deux concepts en jeu qui rendent possibles les valeurs de retour multiples. Tout d'abord, lorsque nous plaçons une virgule entre les valeurs, nous créons un tuple (c'est-à-dire une liste immuable) :

>>> 2, 3
(2, 3)
>>> 17, 5, 2
(17, 5, 2)

Naturellement, nous pouvons tirer parti de cette syntaxe pour regrouper les valeurs comme celle-ci celle chose que nous devons retourner. Nous pouvons voir comment cela fonctionne en appelant notre fonction sur la ligne de commande :

>>> operations(3, 5)
(8, 15)
>>> operations(9, 5)
(14, 45)

En d'autres termes, si nous devions appeler cette fonction, le résultat renvoyé serait un tuple, et non deux valeurs distinctes.

Cela nous amène à notre deuxième question. Comment pouvons-nous alors séparer le tuple en variables individuelles ? Cela se fait grâce à un concept connu sous le nom de déstructuration ou de déballage. Dans le cas simple, nous utilisons essentiellement la même syntaxe de tuple pour créer deux nouvelles maisons pour nos deux valeurs. Vous pouvez probablement imaginer à quoi cela ressemblerait si nous augmentions le nombre d'opérations renvoyées :

def operations(x, y):
  return x + y, x * y, x ** y

addition, multiplication, power = operations(4, 4)

Ce qui est cool avec la déstructuration, c'est que nous pouvons supprimer des valeurs dont nous ne nous soucions pas :

addition, *_ = operations(10, 11)

Ici, nous stockons le résultat de l'addition dans sa propre variable et nous vidons les deux autres valeurs dans une variable temporaire à l'aide de l'astérisque. Le résultat ressemble à ceci :

>>> addition, *_ = operations(10, 11)
>>> _
[110, 100000000000]
>>> addition
21

Maintenant, vous pouvez voir que notre fonction ne renvoie pas vraiment trois valeurs mais plutôt une liste de trois valeurs. Nous pouvons ensuite traiter cette liste au besoin.

Est-il possible de renvoyer plusieurs valeurs en Python ?

Alors, maintenant que nous avons passé en revue certains des concepts sous-jacents entourant les fonctions et leurs valeurs de retour, comment vous sentez-vous ? Pensez-vous qu'il est possible de renvoyer plusieurs valeurs à partir d'une fonction en Python ? Je dirais que ce n'est pas le cas, mais je peux voir pourquoi les gens pourraient dire le contraire. C'est juste un peu bizarre étant donné que cela peut être accompli dans à peu près n'importe quelle autre langue qui a des listes. Par exemple, diriez-vous que vous renvoyez plusieurs valeurs dans cet exemple Java ?

public static int[] operations(int x, int y) {
    return new int[] {x + y, x * y};
}

Peut-être parce que Python n'a pas de typage statique, les gens pourraient se sentir plus enclins à affirmer que les fonctions Python peuvent renvoyer plusieurs valeurs. Ces indices de type vous font-ils changer d'avis ?

def operations(x: int, y: int) -> tuple[int, int]:
  return x + y, x * y

Sinon, pas de soucis ! Je ne suis pas ici pour dire aux gens comment penser, juste ici pour offrir une autre perspective. Cela dit, j'ai pris le temps de parcourir les commentaires pour voir si quelqu'un avait une critique similaire à moi, et il y en avait quelques-unes. Fait intéressant, Santiago ne se souciait pas vraiment du pédantisme.

Techniquement, oui. Mais vous, en tant que développeur, renvoyez deux valeurs différentes.

Le fait que Python crée un tuple est important, mais pas nécessairement pertinent dans ce contexte.

– Santiago (@svpino) 19 avril 2021

En tant qu'éducateur, je n'aime pas cette réponse. Il est certainement important que les gens comprennent ce qui se passe réellement, n'est-ce pas ? S'ils suivent simplement l'idiome, ils ne rencontreront probablement pas de problèmes, mais cela semble un peu trompeur malgré tout.

Cela dit, je n'essaie pas de diss Santiago. J'adore son contenu et il a beaucoup fait pour éliminer le contrôle d'accès dans la communauté. Comme vous le savez probablement, j'ai passé une bonne partie de mon temps à me plaindre du contrôle d'accès dans le domaine de la technologie, et je pense que Santiago a fait beaucoup pour s'assurer que la communauté accepte autant de personnes que possible. J'espère que ce petit message ne me mettra pas sur son mauvais côté! Je pensais juste que ce serait une excellente opportunité d'enseignement.

Comme toujours, si vous aimez cet article, je vous encourage à rester. Vous pouvez trouver les articles pertinents ci-dessous. Alternativement, vous pouvez montrer votre soutien en consultant mon article sur la façon de développer la communauté. Sinon, merci d'être passé ! Prenez soin de vous.


Balise Java