1214 Stimmen

Wie kann ich am besten mehrere Werte aus einer Funktion zurückgeben?

Der kanonische Weg, um mehrere Werte in Sprachen, die dies unterstützen, zurückzugeben, ist oft Tupling .

Option: Verwendung eines Tupels

Betrachten Sie dieses triviale Beispiel:

def f(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return (y0, y1, y2)

Dies wird jedoch schnell problematisch, wenn die Anzahl der zurückgegebenen Werte steigt. Was ist, wenn Sie vier oder fünf Werte zurückgeben wollen? Sicher, man könnte sie weiter tupeln, aber dann vergisst man leicht, welcher Wert wo ist. Außerdem ist es ziemlich unschön, sie dort auszupacken, wo man sie erhalten möchte.

Option: Verwendung eines Wörterbuchs

Der nächste logische Schritt scheint die Einführung einer Art von "Aufzeichnungsnotation" zu sein. In Python ist der offensichtliche Weg, dies zu tun, die Verwendung einer dict .

Bedenken Sie Folgendes:

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0': y0, 'y1': y1 ,'y2': y2}

(Nur um das klarzustellen: y0, y1 und y2 sind nur als abstrakte Bezeichner gedacht. Wie bereits erwähnt, würden Sie in der Praxis sinnvolle Bezeichner verwenden).

Jetzt haben wir einen Mechanismus, mit dem wir ein bestimmtes Mitglied des zurückgegebenen Objekts herausprojizieren können. Zum Beispiel,

result['y0']

Option: Verwendung einer Klasse

Es gibt aber auch eine andere Möglichkeit. Wir könnten stattdessen eine spezialisierte Struktur zurückgeben. Ich habe dies im Kontext von Python beschrieben, aber ich bin sicher, dass es auch für andere Sprachen gilt. Wenn Sie in C arbeiten würden, wäre dies in der Tat die einzige Möglichkeit. So geht's:

class ReturnValue:
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return ReturnValue(y0, y1, y2)

In Python sind die beiden vorgenannten vielleicht sehr ähnlich, was das Klempnerhandwerk angeht - schließlich { y0, y1, y2 } nur als Einträge in der internen Datenbank __dict__ der ReturnValue .

Es gibt jedoch eine zusätzliche Funktion, die Python für winzige Objekte bereitstellt, nämlich die __slots__ Attribut. Die Klasse könnte wie folgt ausgedrückt werden:

class ReturnValue(object):
  __slots__ = ["y0", "y1", "y2"]
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

De la Python-Referenzhandbuch :

En __slots__ Deklaration nimmt eine Folge von Instanzvariablen und reserviert in jeder Instanz gerade genug Platz, um einen Wert für jede Variable zu speichern. Es wird Platz gespart, weil __dict__ wird nicht für jede Instanz erstellt.

Option: Verwendung einer Datenklasse (Python 3.7+)

Verwenden Sie die neuen Datenklassen von Python 3.7, um eine Klasse mit automatisch hinzugefügten speziellen Methoden, Typisierung und anderen nützlichen Werkzeugen zurückzugeben:

@dataclass
class Returnvalue:
    y0: int
    y1: float
    y3: int

def total_cost(x):
    y0 = x + 1
    y1 = x * 3
    y2 = y0 ** y3
    return ReturnValue(y0, y1, y2)

Option: Verwendung einer Liste

Ein weiterer Vorschlag, den ich übersehen hatte, stammt von Bill the Lizard:

def h(x):
  result = [x + 1]
  result.append(x * 3)
  result.append(y0 ** y3)
  return result

Das ist allerdings meine unbeliebteste Methode. Ich vermute, dass ich durch die Erfahrung mit Haskell verdorben bin, aber die Idee von Listen mit gemischten Typen hat sich für mich immer unangenehm angefühlt. In diesem speziellen Beispiel ist die Liste -nicht- vom gemischten Typ, aber es ist denkbar, dass sie es sein könnte.

Eine Liste, die auf diese Weise verwendet wird, bringt in Bezug auf das Tupel wirklich nichts, soweit ich das beurteilen kann. Der einzige wirkliche Unterschied zwischen Listen und Tupeln in Python ist, dass Listen änderbar während Tupel dies nicht sind.

Ich persönlich neige dazu, die Konventionen aus der funktionalen Programmierung zu übernehmen: Listen für eine beliebige Anzahl von Elementen desselben Typs und Tupel für eine feste Anzahl von Elementen eines bestimmten Typs.

Frage

Nach der langen Präambel kommt die unvermeidliche Frage. Welche Methode ist (Ihrer Meinung nach) die beste?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X