Ich habe einige Funktionen in meinem Code, die entweder ein Objekt oder ein iterbares Objekt als Eingabe akzeptieren. Mir wurde beigebracht, für alles sinnvolle Namen zu verwenden, aber ich bin mir nicht sicher, wie ich mich hier verhalten soll. Was soll ich einen Parameter nennen, der ein einzelnes Objekt oder ein iterbares Objekt haben kann? Ich habe mir zwei Ideen einfallen lassen, aber ich mag keines von beiden:
FooOrManyFoos
- Dies drückt aus, was vor sich geht, aber ich könnte mir vorstellen, dass jemand, der nicht daran gewöhnt ist, Schwierigkeiten haben könnte, sofort zu verstehen, was es bedeutet. param
- Ein generischer Name. Dies macht deutlich, dass es mehrere Dinge sein kann, erklärt aber nichts darüber, wofür der Parameter verwendet wird. Normalerweise nenne ich iterables von Objekten nur den Plural von dem, was ich ein einzelnes Objekt nennen würde. Ich weiß, dass dies etwas zwanghaft erscheinen mag, aber Python soll (unter anderem) die Lesbarkeit betreffen.
Ich habe einige Funktionen in meinem Code, die entweder ein Objekt oder ein iterbares Objekt als Eingabe akzeptieren.
Das ist eine sehr außergewöhnliche und oft sehr schlechte Sache. Es ist trivial vermeidbar.
d. h. übergeben Sie [foo] anstelle von foo, wenn Sie diese Funktion aufrufen.
Sie können dies nur rechtfertigen, wenn (1) Sie eine installierte Software-Basis haben, die ein Formular erwartet (iterable oder singleton), und (2) Sie es erweitern müssen, um den anderen Anwendungsfall zu unterstützen. Damit. Sie tun nur , wenn Sie eine vorhandene Funktion mit einer vorhandenen Codebasis erweitern.
Wenn dies eine Neuentwicklung ist, tun Sie dies nicht.
Ich habe zwei Ideen gefunden, aber ich mag keines von beiden:
[Nur zwei?]
FooOrManyFoos - Dies drückt aus, was vor sich geht, aber ich könnte mir vorstellen, dass jemand, der nicht daran gewöhnt ist, Schwierigkeiten haben könnte, sofort zu verstehen, was es bedeutet
Was? Willst du sagen, dass du KEINE andere Dokumentation und kein anderes Training bereitstellst? Keine Unterstützung? Kein Rat? Wer ist der "jemand, der nicht daran gewöhnt ist"? Rede mit ihnen. Nimm dir keine Dinge über sie vor.
Verwenden Sie auch keine führenden Großbuchstaben.
param - Ein generischer Name. Dies macht deutlich, dass es mehrere Dinge sein kann, erklärt aber nichts darüber, wofür der Parameter verwendet wird.
Schrecklich. Noch nie. Machen. Dies.
Ich habe in der Python-Bibliothek nach Beispielen gesucht. Die meisten Funktionen, die dies tun, haben einfache Beschreibungen.
isinstance (Objekt, Klasseninfo)
Sie nennen es "classinfo" und es kann eine Klasse oder ein Tupel von Klassen sein.
Sie könnten das auch tun.
Sie müssen den allgemeinen Anwendungsfall und die Ausnahmen berücksichtigen. Befolgen Sie die 80/20-Regel.
80% der Zeit, können Sie dies durch ein iterable ersetzen und dieses Problem nicht haben.
In den verbleibenden 20% der Fälle haben Sie eine installierte Basis von Software, die auf einer Annahme basiert (entweder iterierbar oder einzelnes Element) und Sie müssen den anderen Fall hinzufügen. Ändern Sie den Namen nicht, ändern Sie einfach die Dokumentation. Wenn es "foo" sagen würde, sagt es immer noch "foo", aber Sie lassen es ein iterables von "foo's" akzeptieren, ohne die Parameter zu ändern. Wenn es "foo_list" oder "foo_iter" sagen würde, dann würde es immer noch "foo_list" oder "foo_iter" heißen, aber es toleriert ruhig ein Singleton ohne zu brechen.
80% des Codes ist das Vermächtnis ("foo" oder "foo_list")
20% des Codes ist das neue Feature ("foo" kann eine iterierbare oder "foo_list" kann ein einzelnes Objekt sein.)
Ich denke, ich bin ein wenig zu spät zur Party, aber ich bin überrascht, dass niemand einen Dekorateur vorgeschlagen hat.
%Vor%Ich sah ein ähnliches Muster in einem von Alex Martellis Beiträgen, aber ich erinnere mich nicht an den Link aus der Hand.
Es klingt, als würdest du dich über die Hässlichkeit von Code quälen wie:
%Vor%Ich schlage vor, die Benutzeroberfläche nicht zu überlasten, um zwei verschiedene Fälle zu behandeln. Ich tendiere dazu, Code zu schreiben, der die Wiederverwendung favorisiert und die Benennung von Methoden gegenüber cleverer dynamischer Verwendung von Parametern klarstellt:
%Vor%Oft beginne ich mit diesem einfachen Muster, habe dann aber die Möglichkeit, den Fall "Viele" zu optimieren, wenn Effizienzgewinne erzielt werden, die die zusätzliche Komplexität des Codes und die teilweise Duplizierung der Funktionalität ausgleichen. Wenn diese Konvention übermäßig verbal erscheint, kann man sich für Namen wie "ProcessWidget" und "ProcessWidgets" entscheiden, obwohl der Unterschied zwischen den beiden ein einfach zu verpassendes Zeichen ist.
Sie können * args magic (varargs) verwenden, um Ihre Parameter immer iterierbar zu machen.
Übergeben Sie ein einzelnes Element oder mehrere bekannte Elemente als normale Funktionsargumente wie func (arg1, arg2, ...) und übergeben Sie iterierbare Argumente mit einem Sternchen wie func (* args )
Beispiel:
%Vor%Können Sie Ihren Parameter auf sehr hohem Niveau benennen? Leute, die den Code lesen, sind mehr daran interessiert zu wissen, was der Parameter repräsentiert ("Clients") als was ihr Typ ist ("list_of_tuples"); Der Typ kann in der Funktionsdokumentationszeichenfolge definiert werden, was eine gute Sache ist, da er sich in der Zukunft ändern kann (der Typ ist manchmal ein Implementierungsdetail).
Ich würde mit einem Namen gehen, der erklärt, dass der Parameter eine Instanz oder eine Liste von Instanzen sein kann. Sage one_or_more_Foo_objects
. Ich finde es besser als die bland param
.
Ich würde 1 Sache machen,
%Vor%Also müssen Sie sich nicht mehr um seinen Namen kümmern.
in einer Funktion, die Sie versuchen sollten, eine Aktion zu erhalten, den gleichen Parametertyp zu akzeptieren und den gleichen Typ zurückzugeben.
Anstatt die Funktionen mit ifs zu füllen, könnten Sie 2 Funktionen haben.
Da es Ihnen egal ist, welche Art von iterierbar Sie erhalten, können Sie versuchen, einen Iterator für den Parameter mit iter () zu erhalten. Wenn iter () eine TypeError-Exception auslöst, ist der Parameter nicht iterierbar, also erstellen Sie eine Liste oder ein Tupel des einen Items, das iterierbar ist und Bobs Onkel.
%Vor%Das einzige Problem bei diesem Ansatz ist, wenn foo eine Zeichenkette ist. Eine Zeichenfolge ist iterierbar. Wenn Sie also eine einzelne Zeichenfolge anstelle einer Liste von Zeichenfolgen übergeben, werden die Zeichen in einer Zeichenfolge durchlaufen. Wenn dies ein Problem darstellt, können Sie einen if-Test hinzufügen. An dieser Stelle wird es immer lauter, wenn es sich um einen Standardcode handelt, also würde ich es in seine eigene Funktion aufteilen.
%Vor%Im Gegensatz zu einigen der Antworten möchte ich dies tun, da es eine Sache eliminiert, die der Anrufer bei der Verwendung Ihrer API falsch verstehen könnte. "Seien Sie in dem, was Sie erzeugen, konservativ, aber in dem, was Sie akzeptieren, liberal."
Um Ihre ursprüngliche Frage zu beantworten, d. h. wie Sie den Parameter benennen sollten, würde ich trotzdem "foos" verwenden, obwohl Sie ein einzelnes Element akzeptieren, da Ihre Absicht eine Liste akzeptiert. Wenn es nicht iterierbar ist, ist das technisch ein Fehler, auch wenn Sie einen für den Aufrufer korrigieren, da es wahrscheinlich ist, dass nur das eine Element verarbeitet wird. Auch wenn der Aufrufer denkt, müssen sie sogar ein Item iterierbar übergeben, nun, das wird natürlich gut funktionieren und erfordert sehr wenig Syntax, also warum sich darum sorgen, ihr Missverständnis zu korrigieren?
Ich arbeite jetzt an einem ziemlich großen Projekt und wir geben Karten herum und rufen nur unseren Parameter map
auf. Der Karteninhalt variiert abhängig von der Funktion, die aufgerufen wird. Dies ist wahrscheinlich nicht die beste Situation, aber wir verwenden eine Menge des gleichen Codes auf den Karten, so dass Kopieren und Einfügen einfacher ist.
Ich würde sagen, anstatt es zu benennen, was es ist, sollten Sie es benennen, wofür es verwendet wird. Achte auch nur darauf, dass du in
nicht auf einem nicht iterierbaren Wert aufrufen kannst.
Tags und Links python naming-conventions