Übergeben eines Sammlungsarguments ohne Entpacken seines Inhalts

8

Frage: Was sind die Vor- und Nachteile des Schreibens von __init__ , das eine Sammlung direkt als Argument verwendet, anstatt den Inhalt zu entpacken?

Kontext: Ich schreibe eine Klasse, um Daten aus mehreren Feldern in einer Datenbanktabelle zu verarbeiten. Ich durchforste einige große (~ 100 Millionen Zeilen) Abfrageergebnisse und übergebe jeweils eine Zeile an eine Klasse, die die Verarbeitung durchführt. Jede Zeile wird als Tupel (oder optional als Wörterbuch) aus der Datenbank abgerufen.

Diskussion: Angenommen, ich interessiere mich für genau drei Felder, aber was in meine Klasse gelangt, hängt von der Abfrage ab und die Abfrage wird vom Benutzer geschrieben. Der einfachste Ansatz könnte einer der folgenden sein:

%Vor%

Hier sind einige Beispiele für Zeilen, die an eine neue Instanz übergeben werden können:

%Vor%

Wenn man mit dem oben genannten konfrontiert wird, läuft Direct immer (zumindest bis zu diesem Punkt), ist aber sehr wahrscheinlich fehlerhaft (GIGO). Es braucht ein Argument und weist es genau wie gegeben zu, also könnte es ein Tupel oder eine Liste beliebiger Größe sein, ein Null-Wert, eine Funktionsreferenz usw. Dies ist die schnellste und schmutzigste Art, die ich mir vorstellen kann, um das zu initialisieren Objekt, aber ich fühle mich wie die Klasse sollte sich sofort beschweren, wenn ich es Daten geben, es ist eindeutig nicht entworfen, damit umzugehen.

Simple behandelt bad1 korrekt, ist fehlerhaft, wenn bad2 angegeben wurde, und gibt einen Fehler aus, wenn bad3 angegeben wird. Es ist praktisch, die Eingaben von bad1 effektiv zu kürzen, aber nicht die Fehler, die von bad2 kommen würden. Dieser fühlt sich naiv und inkonsequent.

Unpack scheint der sicherste Ansatz zu sein, da in allen drei "schlechten" Fällen ein Fehler auftritt. Das letzte, was wir tun wollen, ist, unsere Datenbank still mit schlechten Informationen zu füllen, oder? Es nimmt das Tupel direkt, aber erlaubt mir, seinen Inhalt als unterschiedliche Attribute zu identifizieren, anstatt mich zu zwingen, auf Indizes zu verweisen, und beschwert sich, wenn das Tupel die falsche Größe hat.

Auf der anderen Seite, warum eine Sammlung überhaupt weitergeben? Da ich weiß, dass ich immer drei Felder möchte, kann ich __init__ definieren, um explizit drei Argumente zu akzeptieren, und entpacke die Sammlung mit dem * -Operator, wenn ich sie an das neue Objekt übergebe:

%Vor%

Die einzigen Unterschiede, die ich sehe, sind, dass die __init__ -Definition etwas verbaler ist und wir TypeError anstelle von ValueError erhöhen, wenn das Tupel die falsche Größe hat. Philosophisch gesehen scheint es sinnvoll zu sein, wenn wir eine Gruppe von Daten (eine Zeile einer Abfrage) nehmen und ihre Teile (drei Felder) untersuchen, sollten wir eine Gruppe von Daten (das Tupel) übergeben, aber ihre Teile speichern (die drei Attribute). Also wäre Unpack besser.

Wenn ich eine unbestimmte Anzahl von Feldern anstelle von immer drei akzeptieren möchte, habe ich immer noch die Wahl, das Tupel direkt zu übergeben oder beliebige Argumentlisten (* args, ** kwargs) und * -operator entpacken zu verwenden. Also frage ich mich, ist das eine völlig neutrale Stilentscheidung?

    
Air 20.06.2013, 20:56
quelle

1 Antwort

6

Diese Frage wird wahrscheinlich am besten beantwortet, indem Sie die verschiedenen Ansätze ausprobieren und sehen, was für Sie am sinnvollsten ist und am leichtesten von anderen verstanden wird, die Ihren Code lesen .

Nun, da ich mehr Erfahrung habe, würde ich mich fragen, wie ich auf diese Werte zugreifen möchte?

Wenn ich auf einen der Werte in dieser Sammlung zugreife, verwende ich wahrscheinlich die meisten oder alle der Werte in derselben Subroutine oder Code-Sektion? Wenn dem so ist, ist der "direkte" Ansatz eine gute Wahl ; es ist das kompakteste und lässt mich über die Sammlung als eine Sammlung nachdenken bis zu dem Punkt, dass ich absolut darauf achten muss, was drin ist.

Wenn ich andererseits hier einige Werte verwende, möchte ich mich nicht ständig daran erinnern, auf welchen Index ich zugreifen möchte, oder Ausführlichkeit in Form von Wörterbuchschlüsseln hinzufügen, wenn ich direkt darauf verweisen könnte zu den Werten mit separat benannten Attributen. Ich würde in diesem Fall wahrscheinlich den "direkten" Ansatz vermeiden, so dass ich nur daran denken muss, dass es eine Sammlung gibt, wenn die Klasse zuerst initialisiert wird.

Jeder der verbleibenden Ansätze beinhaltet die Aufteilung der Sammlung in verschiedene Attribute, und ich denke, der klare Gewinner ist hier der "Explicit" -Ansatz . Die Ansätze "Einfach" und "Entpacken" teilen eine verborgene Abhängigkeit von der Reihenfolge der Sammlung, ohne einen wirklichen Vorteil zu bieten.

    
Air 15.12.2014, 23:30
quelle