2012-09-19 12 views
5

Ich habe mir den Quellcode für ein Open Source-Paket angesehen, das ich verwende. Fast jede Funktion verwendet * Argumente anstelle von benannten Argumenten. Ich finde es schwer zu folgen und den Code zu verwenden, denn jedes Mal, wenn ich eine Funktion aufrufen möchte, muss ich zurückgehen, den Quellcode durchgehen und herausfinden, welche Argumente und in welcher Reihenfolge sie sein sollten. Die Frage, die ich habe, ist diese: Gibt es einen zwingenden Grund, * Argumente in jeder Funktion zu verwenden, oder ist das ein Missbrauch des Konzepts? Danke, -bKorrekter Gebrauch vs. über Verwendung von * Argumenten in Python

+0

Wenn es * Args gibt, muss es einen (genauen!) Docstring geben. – James

+0

Welches Paket ist das? Nicht um das Schuldspiel zu spielen, aber sie haben vielleicht einen triftigen Grund. –

Antwort

4

Dies könnte eine persönliche Argumentation sein, aber ich verwende nur * Args und ** Kwargs, wenn ich viele optionale Felder habe, in denen einige Felder nur in einem bestimmten Kontext verwendet werden.

Die einzige andere Gelegenheit, die ich Args verwendet habe, ist, wenn ich einen XML-RPC-Client für eine Cloud-API baute. Da ich gerade Parameter an eine darunterliegende Ebene übergab und da die Funktion dynamisch erzeugt wurde, hatte ich keine andere Wahl, als * Argumente zu verwenden, da ich vorher nicht alle Parameter kennen konnte.

In den meisten Fällen werden Sie es nicht einmal brauchen. Ich halte es hauptsächlich für Faulheit.

Einige Leute, die aus Java und C# kommen, könnten dies als Ersatz für "params" verwenden, aber es gibt so viele Möglichkeiten, optionale Parameter in Python zu übergeben.

Und ich stimme zu, dass selbst wenn Sie * Args verwenden, sollten Sie eine sehr gute Dokumentation haben.

+0

In zwei Jahren Codierung C# Ich habe 'params' zweimal verwendet. In einem Monat Python habe ich '(* args, ** kwargs)' so oft gesehen, dass es meine Augen bluten lässt. Ich würde empfehlen, es sparsam zu verwenden; Es ist ein Werkzeug, das verwendet werden sollte, um ein sehr spezifisches Problem zu lösen. Und wie wir wissen, wenn Sie Leuten ein Werkzeug geben, das so einfach zu benutzen ist, werden sie es zu oft missbrauchen und missbrauchen. – Dagrooms

3

Mit *args in jeder Funktion ist eine schlechte Idee, weil es Fehler im Code (Aufruf eine Funktion mit der falschen Anzahl von Argumenten) maskiert. Ich nehme an, die Faustregel sollte sein, nur *args zu verwenden, wenn Sie *args benötigen.

2

Wenn es keinen zwingenden Grund gibt, *args zu verwenden, ist es ein Missbrauch des Konzepts. Gewöhnlich gibt es gute Namen für Argumente, die das Verständnis erleichtern. Auch wenn es nicht, (x, y, z) sagt Ihnen mehr als (*args).

Und darüber hinaus macht Code besser lesbar, es hilft auch, um Fehler abzufangen (zB wenn Sie eine (x, y, z) Funktion mit (2, 3) rufen Sie beim Aufruf einen Fehler bekommen, anstatt tief in der Funktion), ist es in der Regel prägnanten und es kann sogar effizienter sein.

Aber es gibt manchmal zwingende Gründe für die weit verbreitete Verwendung von *args.

Wenn Sie z. B. ein niedrigeres Modul (C oder nicht) einbinden und eine perfekte Weiterleitung durchführen möchten, ist es einfacher mit *args. Dies umso mehr, wenn Sie den Wrapper-Code automatisch generieren, anstatt ihn manuell zu schreiben. Natürlich ist das immer noch ein Kompromiss - für den Entwickler des Wrapper-Moduls ist es viel einfacher, aber für die Benutzer schwieriger - aber manchmal ist der Kompromiss wert, genommen zu werden.

Ohne zu wissen, auf welches Paket Sie sich beziehen, ist es unmöglich zu erraten, ob es sich um einen zwingenden Anwendungsfall oder einen Missbrauch handelt.

3

In der Zen of Python wird uns gesagt, explizite über implizite zu bevorzugen. Explizite Argumente sollten wann immer möglich verwendet werden.

+1

+1, zitiert aus dem Zen. – nneonneo

+1

@nneonneo Zitat aus dem Zen ohne weitere Kommentare ist ziemlich nutzlos. Die Richtlinien im Zen von Python sind großartig, aber nicht nur weil sie im Zen von Python sind, sie sind gute Ideen für * gute Gründe *. Sich das Zen von Python zu merken, ohne * die Gründe für diese Richtlinien zu verstehen (damit Sie erkennen können, wenn Sie von ihnen abweichen), hilft Ihnen nicht, sie gut anzuwenden. – Ben

+0

@Ben, ich dachte nicht, dass es mein Platz war, darüber zu spekulieren, warum dieser bestimmte Gegenstand im Zen ist. In diesem Fall dachte ich, es sei ziemlich offensichtlich - Explizite ist leichter zu verstehen und zu folgen. Ich habe auch festgestellt, dass die Arbeit mit den gleichen Prinzipien, die Ihren Plattform-Designer leiten, alles besser macht, nicht nur in Python. –

2

Wenn Sie eine unbekannte Funktion umbrechen (die von Decorators zurückgegebenen Funktionen tun dies oft), müssen Sie oft (*args, **kwargs) verwenden.

Einige Klassenhierarchien verwenden (*args, **kwargs) in Methoden, die unterschiedliche Signaturen an verschiedenen Klassen in den Hierarchien benötigen (__init__ ist ein Hauptschuldiger). Es ist wirklich hilfreich, wenn Sie das vermeiden können, aber kann notwendig sein, mit mehreren Vererbungshierarchien in einer gesunden Art und Weise zu arbeiten (oder so vernünftig wie möglich ist, mit mehrfachen Vererbung, zumindest).

Ich benutze manchmal **kwargs, wenn ich eine große Anzahl von optionalen Argumenten habe, aber das erfordert eine Menge Dokumentation.

In einer Funktion, die die *args selbst ist raubend (anstatt sie zu einer anderen Funktion mit einer unbekannten Signatur, wie sie in dem Dekorateur oder Klassen Erbfällen vorbei), dann neige ich dazu, zu denken, dass *args sollte so gut wie nie, außer verwendet werden bedeuten "null oder mehr der gleichen Art von Sache". Und in diesem Fall sollten Sie es benennen *websites oder *spaceships oder *watermelons, nicht *args. Eine Reihe von nicht verwandten Parametern sollte nicht in *args gequetscht werden. Noch schlimmer wäre es für die Funktion *args zu verwenden, um "ein x, ein y und ein z, oder auch ein x und ein z" zu nehmen, wobei der zweite Parameter verschiedene Dinge abhängig davon durchführt, wie viele Parameter übergeben werden. An diesem Punkt sollten sie eindeutig alle Namen und Standardwerte haben (selbst wenn es nur der Standard None ist, dann sehen Sie in der Funktion, welche Muster nicht None sind) und werden nach Schlüsselwort und nicht nach Position übergeben.

Verwandte Themen