Es stimmt, die meisten Programmiersprachen machen Parameter , um einen Teil des Funktionsaufrufs Vertrag, aber dies nicht brauchen , so zu sein. Warum sollte es? Mein Verständnis der Frage ist also, ob Python sich in dieser Hinsicht von anderen Programmiersprachen unterscheidet. Beachten Sie neben anderen guten Antworten für Python 2 Folgendes:
__named_only_start = object()
def info(param1,param2,param3,_p=__named_only_start,spacing=10,collapse=1):
if _p is not __named_only_start:
raise TypeError("info() takes at most 3 positional arguments")
return str(param1+param2+param3) +"-"+ str(spacing) +"-"+ str(collapse)
Der einzige Weg, wie ein Anrufer Argumente spacing
und collapse
Position (ohne Ausnahme) liefern kann, wäre:
info(arg1, arg2, arg3, module.__named_only_start, 11, 2)
Die Konvention, keine privaten Elemente zu verwenden, die bereits zu anderen Modulen gehören, ist in Python sehr grundlegend. Wie bei Python selbst würde diese Konvention für Parameter nur teilweise durchgesetzt.
Andernfalls müssten Anrufe die folgende Form haben:
info(arg1, arg2, arg3, spacing=11, collapse=2)
Ein Anruf
info(arg1, arg2, arg3, 11, 2)
würde dem Parameter den Wert 11 zuweisen _p
und eine Ausnahme durch den ersten Befehl der Funktion auslösen.
Eigenschaften:
- Vorherige Parameter
_p=__named_only_start
werden positionell (oder namentlich) zugelassen.
- Parameter nach
_p=__named_only_start
müssen nur namentlich angegeben werden (es sei denn, Kenntnisse über das spezielle Sentinel-Objekt __named_only_start
werden erhalten und verwendet).
Vorteile:
- Parameter sind in Anzahl und Bedeutung explizit (später, wenn natürlich auch gute Namen gewählt werden).
- Wenn der Sentinel als erster Parameter angegeben wird, müssen alle Argumente namentlich angegeben werden.
- Beim Aufrufen der Funktion ist es möglich, in den Positionsmodus zu wechseln, indem das Sentinel-Objekt
__named_only_start
an der entsprechenden Position verwendet wird.
- Eine bessere Leistung als bei anderen Alternativen ist zu erwarten.
Nachteile:
Die Überprüfung erfolgt zur Laufzeit, nicht zur Kompilierungszeit.
- Verwendung eines zusätzlichen Parameters (wenn auch kein Argument) und einer zusätzlichen Prüfung. Geringe Leistungsverschlechterung in Bezug auf reguläre Funktionen.
- Funktionalität ist ein Hack ohne direkte Unterstützung durch die Sprache (siehe Hinweis unten).
- Beim Aufrufen der Funktion kann mit dem Sentinel-Objekt
__named_only_start
in der richtigen Position in den Positionsmodus gewechselt werden . Ja, das kann man auch als Profi sehen.
Bitte beachten Sie, dass diese Antwort nur für Python 2 gültig ist. Python 3 implementiert den ähnlichen, aber sehr eleganten, sprachunterstützten Mechanismus, der in anderen Antworten beschrieben wird.
Ich habe festgestellt, dass, wenn ich meinen Geist öffne und darüber nachdenke, keine Frage oder die Entscheidung eines anderen dumm, dumm oder einfach nur albern erscheint. Ganz im Gegenteil: Ich lerne normalerweise viel.
_named_only_start
, ist es auch unmöglich, sie von einem externen Modul aus zu referenzieren, das ein Pro und ein Contra herausnimmt. (einzelne führende Unterstriche im Modulumfang sind privat, IIRC)__named_only_start
als auch einnamed_only_start
(kein anfänglicher Unterstrich) haben, wobei der zweite angibt, dass der benannte Modus "empfohlen" wird, jedoch nicht auf der Ebene der "aktiven Werbung" (da einer öffentlich ist und der andere ist nicht). Die "Privatsphäre"_names
, mit Unterstrichen zu beginnen, wird von der Sprache nicht sehr stark durchgesetzt: Sie kann leicht durch die Verwendung spezifischer (nicht *) Importe oder qualifizierter Namen umgangen werden. Aus diesem Grund bevorzugen einige Python-Dokumente den Begriff "nicht öffentlich" anstelle von "privat".Sie können dies auf eine Weise tun, die sowohl in Python 2 als auch in Python 3 funktioniert , indem Sie ein "falsches" erstes Schlüsselwortargument mit einem Standardwert erstellen, der nicht "natürlich" vorkommt. Vor diesem Schlüsselwortargument können ein oder mehrere Argumente ohne Wert stehen:
Dies ermöglicht:
aber nicht:
Wenn Sie die Funktion ändern in:
dann müssen alle Argumente Schlüsselwörter und haben
info(odbchelper)
funktionieren nicht mehr.Auf diese Weise können Sie zusätzliche Keyword-Argumente an einer beliebigen Stelle danach platzieren
_kw
, ohne sie nach dem letzten Eintrag einfügen zu müssen. Dies ist oft sinnvoll, z. B. kann die logische Gruppierung oder alphabetische Anordnung von Schlüsselwörtern bei der Wartung und Entwicklung hilfreich sein.Sie müssen also nicht mehr auf die Verwendung
def(**kwargs)
und den Verlust der Signaturinformationen in Ihrem Smart Editor zurückgreifen . Ihr Gesellschaftsvertrag besteht darin, bestimmte Informationen bereitzustellen, indem Sie (einige von ihnen) dazu zwingen, Schlüsselwörter zu verlangen. Die Reihenfolge, in der diese dargestellt werden, ist irrelevant geworden.quelle
Aktualisieren:
Ich erkannte, dass die Verwendung
**kwargs
das Problem nicht lösen würde. Wenn Ihre Programmierer Funktionsargumente nach Belieben ändern, können Sie beispielsweise die Funktion folgendermaßen ändern:und der alte Code würde wieder brechen (weil jetzt jeder Funktionsaufruf das erste Argument enthalten muss).
Es kommt wirklich darauf an, was Bryan sagt.
Im Allgemeinen sollten beim Ändern von Funktionen neue Argumente immer bis zum Ende gehen. Andernfalls wird der Code beschädigt. Sollte offensichtlich sein.
Wenn jemand die Funktion so ändert, dass der Code beschädigt wird, muss diese Änderung abgelehnt werden.
(Wie Bryan sagt, ist es wie ein Vertrag)
Wenn man sich die Signatur der Funktion (dh
def info(object, spacing=10, collapse=1)
) ansieht, sollte man sofort erkennen, dass jedes Argument, das keinen Standardwert hat, obligatorisch ist.Wofür das Argument ist, sollte in den Docstring gehen.
Alte Antwort (der Vollständigkeit halber aufbewahrt) :
Dies ist wahrscheinlich keine gute Lösung:Sie können Funktionen folgendermaßen definieren:
kwargs
ist ein Wörterbuch, das ein beliebiges Schlüsselwortargument enthält. Sie können überprüfen, ob ein obligatorisches Argument vorhanden ist, und wenn nicht, eine Ausnahme auslösen.Der Nachteil ist, dass es vielleicht nicht mehr so offensichtlich ist, welche Argumente möglich sind, aber mit einer richtigen Dokumentation sollte es in Ordnung sein.
quelle
Die python3-Schlüsselwortargumente (
*
) können in python2.x mit simuliert werden**kwargs
Betrachten Sie den folgenden Python3-Code:
und sein Verhalten:
Dies kann wie folgt simuliert werden: Hinweis: Ich habe mir die Freiheit genommen
TypeError
,KeyError
im Fall "Erforderliches benanntes Argument" zu wechseln. Es wäre nicht zu viel Arbeit, diesen Ausnahmetyp ebenfalls festzulegenUnd Verhalten:
Das Rezept funktioniert genauso gut in python3.x, sollte jedoch vermieden werden, wenn Sie nur python3.x sind
quelle
kwargs.pop('foo')
ist eine Python 2-Sprache? Ich muss meinen Codierungsstil aktualisieren. Ich habe diesen Ansatz immer noch in Python 3 verwendetSie können Ihre Funktionen als
**args
nur empfangend deklarieren . Das würde Schlüsselwortargumente erfordern, aber Sie müssten zusätzliche Arbeit leisten, um sicherzustellen, dass nur gültige Namen übergeben werden.quelle
foo(**kwargs)
. Was gebe ich dazu?foo(killme=True, when="rightnowplease")
dict
.Wie andere Antworten sagen, ist das Ändern von Funktionssignaturen eine schlechte Idee. Fügen Sie am Ende entweder neue Parameter hinzu oder korrigieren Sie jeden Aufrufer, wenn Argumente eingefügt werden.
Wenn Sie dies dennoch tun möchten, verwenden Sie einen Funktionsdekorator und die Funktion inspect.getargspec . Es würde ungefähr so verwendet werden:
Implementierung von
require_named_args
bleibt als Übung für den Leser.Ich würde mich nicht darum kümmern. Es wird jedes Mal langsam, wenn die Funktion aufgerufen wird, und Sie erhalten bessere Ergebnisse, wenn Sie den Code sorgfältiger schreiben.
quelle
Sie könnten den
**
Operator verwenden:Auf diese Weise werden Benutzer gezwungen, benannte Parameter zu verwenden.
quelle
Wenn Sie in Python * args verwenden, bedeutet dies, dass Sie n-Anzahl von Argumenten für diesen Parameter übergeben können. Dies ist eine Liste innerhalb der Funktion, auf die zugegriffen werden soll
und wenn Sie ** kw verwenden, bedeutet dies, dass die Schlüsselwortargumente als Diktat verwendet werden können - Sie können n-Anzahl von kw-Argumenten übergeben, und wenn Sie diesen Benutzer einschränken möchten, müssen Sie die Reihenfolge und die Argumente der Reihe nach eingeben, dann verwenden Sie sie nicht * und ** - (seine pythonische Art, generische Lösungen für große Architekturen bereitzustellen ...)
Wenn Sie Ihre Funktion mit Standardwerten einschränken möchten, können Sie sie überprüfen
quelle
Ich verstehe nicht, warum ein Programmierer überhaupt einen Parameter zwischen zwei anderen hinzufügt.
Wenn Sie möchten, dass die Funktionsparameter mit Namen verwendet werden (z
info(spacing=15, object=odbchelper)
), sollte es keine Rolle spielen, in welcher Reihenfolge sie definiert sind. Sie können also auch die neuen Parameter am Ende setzen.Wenn Sie möchten, dass die Reihenfolge eine Rolle spielt, können Sie nicht erwarten, dass etwas funktioniert, wenn Sie es ändern!
quelle