web-dev-qa-db-fra.com

Comment Python renvoie-t-il plusieurs valeurs d'une fonction?

J'ai écrit le code suivant:

class FigureOut:
   def setName(self, name):
      fullname = name.split()
      self.first_name = fullname[0]
      self.last_name = fullname[1]

   def getName(self):
      return self.first_name, self.last_name

f = FigureOut()
f.setName("Allen Solly")
name = f.getName()
print (name)

Je reçois ce qui suit Output:

('Allen', 'Solly')

Chaque fois que plusieurs valeurs sont renvoyées par une fonction en python, est-ce qu’elles sont toujours converties en un liste de plusieurs valeurs puis renvoyées par la fonction?

L'ensemble du processus est-il identique à la conversion des valeurs multiples en une list de manière explicite, puis à la restitution de la liste, par exemple en Java, car on ne peut renvoyer qu'un seul objet à partir d'une fonction de JAVA?

20
User_Targaryen

Comme l'instruction return dans getName spécifie plusieurs éléments:

def getName(self):
   return self.first_name, self.last_name

Python retournera un objet conteneur qui les contient fondamentalement. 

Dans ce cas, renvoyer un ensemble d'éléments séparés par des virgules crée un Tuple. Plusieurs valeurs ne peuvent être retournées que dans des conteneurs.

Utilisons une fonction plus simple qui renvoie plusieurs valeurs:

def foo(a, b):
    return a, b

Vous pouvez consulter le code d'octet généré en utilisant dis.dis , un désassembleur pour le bytecode Python. Pour les valeurs séparées par des virgules sans parenthèses, voici à quoi ressemble:

>>> import dis
>>> def foo(a, b):
...     return a,b        
>>> dis.dis(foo)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (b)
              6 BUILD_Tuple              2
              9 RETURN_VALUE

Comme vous pouvez le constater, les valeurs sont d'abord chargées dans la pile interne avec LOAD_FAST, puis un BUILD_Tuple (en récupérant les éléments 2 précédents placés dans la pile) est généré. Python sait créer un tuple en raison de la présence de virgules.

Vous pouvez également spécifier un autre type de retour, par exemple une liste, en utilisant []. Dans ce cas, un BUILD_LIST va être émis suivant la même sémantique que son équivalent Tuple:

>>> def foo_list(a, b):
...     return [a, b]
>>> dis.dis(foo_list)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (b)
              6 BUILD_LIST               2
              9 RETURN_VALUE

Le type d'objet renvoyé dépend vraiment de la présence de crochets (pour les tuples, () peut être omis s'il y a au moins une virgule). [] crée des listes et des ensembles {}. Les dictionnaires ont besoin de key:val paires.

Pour résumer, un objet réel est renvoyé. Si cet objet est de type conteneur, il peut contenir plusieurs valeurs donnant l'impression de plusieurs résultats renvoyés. La méthode habituelle consiste alors à les décompresser directement:

>>> first_name, last_name = f.getName()
>>> print (first_name, last_name)

En plus de tout cela, vos méthodes Java s'infiltrent dans Python :-) 

N'utilisez pas de getters lors de l'écriture de classes en Python, utilisez properties. Les propriétés sont le moyen idiomatique de gérer les attributs. Pour plus d'informations à ce sujet, voir la réponse agréable ici .

28

De Python Cookbook v.30

def myfun():
    return 1, 2, 3

a, b, c = myfun()

Bien qu'il semble que myfun() renvoie plusieurs valeurs, un Tuple est en cours de création. Cela semble un peu étrange, mais c’est en fait la virgule qui forme un tuple, pas les parenthèses.

Alors oui, ce qui se passe dans Python est une transformation interne de plusieurs valeurs séparées par des virgules en un tuple et vice-versa. 

Bien qu'il n'y ait pas d'équivalent dans Java , vous pouvez facilement créer ce comportement en utilisant array 'ou quelques Collections comme Lists:

private static int[] sumAndRest(int x, int y) {
    int[] toReturn = new int[2];

    toReturn[0] = x + y;
    toReturn[1] = x - y;

    return toReturn;

}

Exécuté de cette manière:

public static void main(String[] args) {
    int[] results = sumAndRest(10, 5);

    int sum  = results[0];
    int rest = results[1];

    System.out.println("sum = " + sum + "\nrest = " + rest);

}

résultat:

sum = 15
rest = 5
18
joc

Ici, il est en train de retourner Tuple.

Si vous exécutez ce code dans Python 3: 

def get():
    a = 3
    b = 5
    return a,b
number = get()
print(type(number))
print(number)

Sortie: 

<class 'Tuple'>
(3, 5)

Mais si vous modifiez la ligne de code return [a,b] au lieu de return a,b et exécutez: 

def get():
    a = 3
    b = 5
    return [a,b]
number = get()
print(type(number))
print(number)

Sortie:

<class 'list'>
[3, 5]

Il ne renvoie qu'un seul objet contenant plusieurs valeurs. 

Il existe une autre alternative à l'instruction return pour renvoyer plusieurs valeurs, utilisez yield (pour vérifier les détails, voyez ceci Que fait le mot clé "yield" en Python? )

Exemple:

def get():
    for i in range(5):
        yield i
number = get()
print(type(number))
print(number)
for i in number:
    print(i)

Sortie:

<class 'generator'>
<generator object get at 0x7fbe5a1698b8>
0
1
2
3
4
6
Kalpesh Dusane

Les fonctions Python retournent toujours une valeur unique. L'opérateur virgule est le constructeur des tuples. self.first_name, self.last_name est alors évalué comme un tuple et ce soit la valeur réelle renvoyée par la fonction.

3
Goyo

Chaque fois que plusieurs valeurs sont renvoyées d'une fonction en python, est-ce qu'elle convertit toujours les multiples valeurs en un list de plusieurs valeurs, puis le renvoie depuis la fonction ??. 

Je ne fais qu'ajouter un nom et imprimer le résultat renvoyé par la fonction . Le type de résultat est 'Tuple'.

  class FigureOut:
   first_name = None
   last_name = None
   def setName(self, name):
      fullname = name.split()
      self.first_name = fullname[0]
      self.last_name = fullname[1]
      self.special_name = fullname[2]
   def getName(self):
      return self.first_name, self.last_name, self.special_name

f = FigureOut()
f.setName("Allen Solly Jun")
name = f.getName()
print type(name)


Je ne sais pas si vous avez entendu parler de 'first class function'. Python est le langage qui a ' fonction de première classe

J'espère que ma réponse pourra vous aider… __. Bon codage.

2
Junsuk Park

mentionné aussi ici , vous pouvez utiliser ceci:

import collections
Point = collections.namedtuple('Point', ['x', 'y'])
p = Point(1, y=2)
>>> p.x, p.y
1 2
>>> p[0], p[1]
1 2
0
Ghazal