Gibt es eine Konvention für die Rücksendung mehrerer Artikel?

10

Gibt es in Python speziell (ich weiß nicht, ob dies verallgemeinert wird) eine "beste" Möglichkeit, mehrere Elemente von einer Funktion zurückzugeben?

def func1():
    return a,b #equivalent to (a,b)

def func2():
    return[a,b]

def func3():
    return{"valueA":a,"valueB":b}

Das erste ist das, was ich am häufigsten sehe, aber ich glaube, das letzte erstellt besser lesbaren Code, weil Sie Ausgaben benannt haben, aber mir fehlt möglicherweise ein Overhead, der mit dieser Methode erstellt wurde?

Devon Muraoka
quelle
Sie stimmen nicht mehrere Argumente ab. In all diesen Beispielen geben Sie ein einzelnes Ergebnis zurück, das zufällig ein zusammengesetzter Datentyp ist (ein Tupel, eine Liste bzw. ein Wörterbuch). Welcher Datentyp zurückgegeben werden soll, hängt von Ihrer Funktion ab und davon, wie er verwendet werden soll.
Gardenhead
Interessant, ich habe es nie so gesehen, wenn Sie das zu einer Antwort machen, kann ich es akzeptieren
Devon Muraoka

Antworten:

13

Ich denke, die Entscheidungen müssen aus Sicht des Anrufers streng betrachtet werden: Was muss der Verbraucher am wahrscheinlichsten tun?

Und was zeichnet jede Kollektion aus?

  • Auf das Tupel wird in der richtigen Reihenfolge und unveränderlich zugegriffen
  • Auf die Liste wird der Reihe nach zugegriffen und sie kann geändert werden
  • Auf das Diktat wird per Schlüssel zugegriffen

Die Liste und das Tupel sind für den Zugriff gleichwertig, aber die Liste ist veränderbar. Nun, das ist mir als Anrufer egal, wenn ich die Ergebnisse sofort auspacken will:

score, top_player = play_round(players)
# or
idx, record = find_longest(records)

Es gibt hier keinen Grund für mich, mich darum zu kümmern, ob es sich um eine Liste oder ein Tupel handelt, und das Tupel ist auf beiden Seiten einfacher.

Wenn die zurückgegebene Sammlung jedoch als Ganzes aufbewahrt und als Sammlung verwendet werden soll :

points = calculate_vertices(shape)
points.append(another_point)
# Make a new shape

dann könnte es sinnvoll sein, dass die Rückkehr veränderlich ist. Auch hier spielt die Homogenität eine wichtige Rolle. Angenommen, Sie haben eine Funktion zum Durchsuchen einer Sequenz nach wiederholten Mustern geschrieben. Die Informationen, die ich zurückerhalte, sind der Index in der Reihenfolge der ersten Instanz des Musters, die Anzahl der Wiederholungen und das Muster selbst. Das sind nicht die gleichen Dinge. Auch wenn ich die Teile zusammenhalten könnte, gibt es keinen Grund, die Sammlung zu mutieren . Dies ist kein list.

Nun zum Wörterbuch.

Der letzte erstellt besser lesbaren Code, da Sie Ausgaben benannt haben

Ja, Schlüssel für die Felder machen heterogene Daten expliziter, aber es ist auch mit einer gewissen Belastung verbunden. Nochmals für den Fall "Ich werde nur das Zeug auspacken", dies

round_results = play_round(players)
score, top_player = round_results["score"], round_results["top_player"]

(Auch wenn Sie wörtliche Zeichenfolgen für die Schlüssel vermeiden), ist im Vergleich zur Tupelversion unnötiger Aufwand.

Hier stellt sich die dreifache Frage: Wie komplex ist die Sammlung, wie lange wird die Sammlung zusammengehalten, und müssen wir dieselbe Art von Sammlung an verschiedenen Orten verwenden?

Ich würde vorschlagen, dass ein Rückgabewert mit verschlüsseltem Zugriff sinnvoller ist als ein Tupel, wenn mehr als drei Mitglieder vorhanden sind, insbesondere wenn Verschachtelungen vorhanden sind:

shape["transform"]["raw_matrix"][0, 1] 
# vs.
shape[2][4][0, 1]

Das führt zur nächsten Frage: Wird die Sammlung diesen Bereich intakt lassen, irgendwo weg von dem Aufruf, der sie erstellt hat? Der verschlüsselte Zugriff dort hilft absolut der Verständlichkeit.

Die dritte Frage - Wiederverwendung - verweist auf einen einfachen benutzerdefinierten Datentyp als vierte Option, die Sie nicht vorgestellt haben.

Ist die Struktur ausschließlich im Besitz dieser einen Funktion? Oder erstellen Sie an vielen Stellen das gleiche Wörterbuchlayout? Müssen viele andere Teile des Programms mit dieser Struktur arbeiten? Ein wiederholtes Wörterbuchlayout sollte für eine Klasse herausgerechnet werden. Der Bonus besteht darin, dass Sie Verhalten anhängen können: Möglicherweise werden einige der Funktionen, die mit den Daten arbeiten, als Methoden gekapselt.

Eine fünfte gute, leichte Option ist namedtuple(). Dies ist im Wesentlichen die unveränderliche Form des Wörterbuch-Rückgabewerts.

jscs
quelle
Gibt es einen Grund, warum Sie Instanzen von benutzerdefinierten Klassen überhaupt nicht erwähnen? Das sollte die Goto-Lösung in jeder OO-Sprache sein.
Esben Skov Pedersen
1
Dies wird in den vorletzten und vorletzten Absätzen @EsbenSkovPedersen behandelt. "Ein wiederholtes Wörterbuchlayout sollte für eine Klasse herausgerechnet werden."
Jscs
1

Denken Sie nicht an Funktionen, die mehrere Argumente zurückgeben. Konzeptionell ist es am besten, sich Funktionen als Empfangen und Zurückgeben eines einzelnen Arguments vorzustellen. Eine Funktion, die anscheinend mehrere Argumente akzeptiert, erhält tatsächlich nur ein einziges Argument vom Typ Tupel (formal Produkt ). In ähnlicher Weise gibt eine Funktion, die mehrere Argumente zurückgibt, einfach ein Tupel zurück.

In Python:

def func(a, b, c):
  return b, c

könnte umgeschrieben werden als

def func(my_triple):
  return (my_triple[1], my_triple[2])

um den Vergleich deutlich zu machen.

Der erste Fall ist lediglich syntaktischer Zucker für letzteren; Beide erhalten ein Triple als Argument, aber das erste Muster stimmt mit seinem Argument überein, um eine automatische Destrukturierung in seine Bestandteile durchzuführen. Selbst Sprachen ohne vollständigen allgemeinen Mustervergleich lassen daher bei einigen ihrer Typen eine Form des grundlegenden Mustervergleichs zu (Python lässt den Mustervergleich sowohl bei Produkt- als auch bei Datensatztypen zu).


Um auf die vorliegende Frage zurückzukommen: Es gibt keine einzige Antwort auf Ihre Frage, denn es wäre, als würde man fragen: "Was sollte der Rückgabetyp einer beliebigen Funktion sein?" Dies hängt von der Funktion und dem Anwendungsfall ab. Und wenn die "Mehrfachrückgabewerte" wirklich unabhängig sind, sollten sie im Übrigen wahrscheinlich von separaten Funktionen berechnet werden.

Gartenkopf
quelle