2009-05-03 6 views
19

Ich möchte eine große Python-Funktion in kleinere umwandeln. Betrachten Sie zum Beispiel folgendes Code-Snippet:Python: Vermeidung von Pylint-Warnungen über zu viele Argumente

x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 

Natürlich ist dies ein triviales Beispiel. In der Praxis ist der Code komplexer. Mein Punkt ist, dass es viele lokale-scope Variablen enthält, die der extrahierten Funktion übergeben werden müssten, die wie folgt aussehen könnte:

def mysum(x1, x2, x3, x4, x5, x6, x7, x8, x9): 
    x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 
    return x 

Das Problem ist, dass Pylint eine Warnung über zu viele Argumente auslösen würde. Ich konnte die Warnung vermeiden, indem etwas zu tun, wie:

def mysum(d): 
    x1 = d['x1'] 
    x2 = d['x2'] 
    ... 
    x9 = d['x9'] 
    x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 
    return x 

def mybigfunction(): 
    ... 
    d = {} 
    d['x1'] = x1 
    ... 
    d['x9'] = x9 
    x = mysum(d) 

aber dieser Ansatz loos mich hässlich, es erfordert eine Menge Code zu schreiben, die auch redundant ist.

Gibt es einen besseren Weg, es zu tun?

+1

Ich glaube, dass mysum() vereinfacht werden könnte: 'return sum (d.values ​​())' oder zumindest 'return sum ([d [foo] für foo in (' x1 ',' x2 ', .. ., "x9")]). Bin ich zu glücklich, um Listen zu verstehen? – MatrixFrog

+1

Das mysum() ist nur eine Abstraktion, in realen Szenarien ist der Code, der extrahiert werden muss, viel komplexer. Es geht darum, viele Variablen an die extrahierte Funktion zu übergeben und die pylint-Warnung möglichst zu vermeiden (ohne dass pylint explizit dazu gezwungen wird, diese Warnung einfach zu ignorieren). – Anonymous

Antwort

5

Vereinfachen oder zerlegen Sie die Funktion so, dass sie keine neun Argumente benötigt (oder ignorieren Sie pylint, aber Ausweichen wie die vorgeschlagenen, besiegen Sie den Zweck eines Flusenwerkzeugs).

EDIT: Wenn es sich um eine vorübergehende Maßnahme, deaktivieren Sie die Warnung für die jeweilige Funktion in Frage ist einen Kommentar mit, wie hier beschrieben: http://lists.logilab.org/pipermail/python-projects/2006-April/000664.html

Später können Sie für alle Behinderten Warnungen grep.

+0

Mein Ziel ist es, die große Funktion zuerst zu brechen. Dann könnte ich fortfahren, die kleineren Teile weiter zu brechen. Aber ich möchte diese spezifische Pylint-Warnung während des Refactoring-Prozesses vermeiden, wenn dies möglich ist. – Anonymous

12

könnten Sie versuchen Python's variable arguments-Funktion:

def myfunction(*args): 
    for x in args: 
     # Do stuff with specific argument here 
+1

Es ist das gleiche wie mit einer Liste, siehe unten. – Anonymous

6

Vielleicht könnten Sie einige der Argumente in Membervariablen drehen. Wenn Sie so viel Staat brauchen, klingt eine Klasse für mich eine gute Idee.

+0

Funktioniert nicht, wenn ich eine Klassenmethode refaktorieren muss und übergebene Variablen lokal für die große refaktorierte Methode sind und nicht in der gesamten Klasse verwendet werden. – Anonymous

+3

Nein, aber wenn Sie stattdessen einen neuen Typ extrahieren, können Sie möglicherweise einen Teil des Status in Elementvariablen umwandeln. –

0

Python hat einige nette funktionale Programmiertools, die wahrscheinlich gut zu Ihren Bedürfnissen passen. Überprüfen Sie lambda functions und map. Außerdem verwenden Sie dicts, wenn Sie mit Listen besser bedient zu sein scheinen. Versuchen Sie für dieses einfache Beispiel dieses Idiom. Beachten Sie, dass Karte wäre besser und schneller, aber nicht passen Ihre Bedürfnisse:

def mysum(d): 
    s = 0 
    for x in d: 
     s += x 
    return s 

def mybigfunction(): 
    d = (x1, x2, x3, x4, x5, x6, x7, x8, x9) 
    return mysum(d) 

Sie erwähnt eine Menge von lokalen Variablen zu haben, aber ehrlich gesagt, wenn Sie mit Listen (oder Tupel) zu tun haben, sollten Sie verwenden, um Listen und alle diese lokalen Variablen auf lange Sicht ausschließen.

+0

Ich kann keine Liste verwenden. In meinem trivialen Beispiel spielen meine übergebenen Variablen die gleiche Rolle. In einem komplexen Szenario haben die Variablen jedoch unterschiedliche Bedeutungen. Daher würde das Ersetzen ihrer Namen (die eine logische Bedeutung haben) mit Listenelementen, auf die durch den Index zugegriffen wird, die Lesbarkeit des Codes vollständig zerstören. – Anonymous

+2

Sie müssen dann das Diktat verwenden. Das heißt, Sie werden nicht in der Lage sein, Dinge viel zu reinigen, wenn Sie nicht einige Ihrer Anforderungen ändern. Alternativ könnten Sie eine Klasse für all diese Sachen definieren und dann die Logik in verschiedene Klassenmethoden pushen. wahrscheinlich sauberer als ein riesiger Wenn-Dann-Baum, basierend auf einem Diktat, zumindest! – easel

55

Zuerst eine von Perlis's epigrams:

"Wenn Sie eine Prozedur mit 10 Parameter haben, können Sie einige wahrscheinlich vermisst."

Einige der 10 Argumente sind vermutlich verwandt. Gruppiere sie zu einem Objekt und gib das stattdessen weiter.

machen ein Beispiel, denn es in der Frage nicht genügend Informationen ist direkt zu beantworten:

class PersonInfo(object): 
    def __init__(self, name, age, iq): 
    self.name = name 
    self.age = age 
    self.iq = iq 

dann Ihre 10 Argument Funktion:

def f(x1, x2, name, x3, iq, x4, age, x5, x6, x7): 
    ... 

wird:

def f(personinfo, x1, x2, x3, x4, x5, x6, x7): 
    ... 

und der Anrufer ändert sich zu:

personinfo = PersonInfo(name, age, iq) 
result = f(personinfo, x1, x2, x3, x4, x5, x6, x7) 
+3

Ich mag diese Antwort, weil sie zeigt, wie man über das Problem denkt! –

24

Möchten Sie einen besseren Weg, um die Argumente zu übergeben oder einfach nur einen Weg zu stoppen pylint aus Ihnen eine harte Zeit? Wenn letzteres der Fall, scheine ich, daran zu erinnern, dass Sie, indem pylint -controlling Kommentare in Ihrem Code entlang der Linien von der Nörgelei aufhören konnte:

#pylint: disable-msg=R0913 

oder:

#pylint: disable-msg=too-many-arguments 

erinnerte sie wieder zu aktivieren So schnell es geht.

Meiner Meinung nach gibt es nichts von Natur aus falsch mit vielen Argumenten und Lösungen vorbei befürworten sie alle in einem gewissen Behälter Argumente Verpackung löst nicht wirklich keine Probleme, außer pylint Stoppen von Ihnen :-) Gezeter.

Wenn Sie zwanzig Argumente übergeben müssen, übergeben Sie sie. Es kann sein, dass dies erforderlich ist, weil Ihre Funktion zu viel tut und ein Re-Factoring dabei helfen kann, und das sollten Sie sich ansehen. Aber es ist keine Entscheidung wir können wirklich machen, wenn wir nicht sehen, was der "echte" Code ist.

+3

Diese Antwort ermutigt wirklich schlechte Gewohnheiten - lesen Sie jetzt im Jahr 2015 1) prüft mit ihrer Nummer zu deaktivieren - moderne Pylint Versionen unterstützen symbolische Deskriptoren, viel mehr explikative 2) sollte auch einen Kommentar mit einer Erklärung, etwas zu deaktivieren der Grund, warum es durch einen entsprechend erneute Aktivierung 3) soll es nur eine Richtlinie pro Zeile, ausgewogen seine 4) Normalerweise Pylint einen Punkt hat, deaktiviert wird. Code, der mit diesen Grenzwerten kollidiert, ist wahrscheinlich nicht lesbar/nicht wartbar. 5) Anstatt eine Flut von Parametern zu übergeben, ist es viel besser, ein Wörterbuch oder ein benanntes Tupel zu verwenden. –

+3

Igor, deshalb sagte ich "im Sinne von". Verwenden Sie auf jeden Fall Symbolik anstelle von Zahlen, oder einen pro Zeile, oder warum, oder reaktivieren Sie (obwohl Sie überlegen sollten, was das bedeutet, wenn es zuvor deaktiviert wurde - besser wäre eine Methode zum Speichern/Deaktivieren/Wiederherstellen).Nichts davon ändert den Nutzen der Antwort selbst, nämlich pylint anzuweisen, nicht mehr über ein Problem zu warnen, über das der Benutzer nicht wissen will (und die Konsequenzen akzeptiert). – paxdiablo

+2

Der Benutzer ist wahrscheinlich oft in sich selbst widersprüchlich: Pylint ist nicht das expliziteste Werkzeug in diesem Sinne, aber die Warnungen gegeben haben in der Regel viel tiefere Reichweite als das, was die Nachricht scheint zu geben. So könnte der Benutzer * denken * zu wissen, welche Konsequenzen akzeptiert werden, aber er weiß die Implikationen nicht voll zu schätzen. –

14

Sie können die maximal zulässige Anzahl von Argumenten in pylint ganz einfach ändern. Öffnen Sie einfach Ihre pylintrc Datei (generieren Sie es, wenn Sie nicht bereits eines haben) und Änderung:

max-args = 5

zu:

max-args = 6 # oder jeder beliebige Wert, dass Anzüge

Sie

Von Pylint der manual

Angabe aller Optionen geeignet für Ihre Konfiguration und Standards Codierung sein kann tedi ous, so ist es möglich, verwenden Sie eine RC-Datei, um die Standardwerte Werte anzugeben. Pylint sucht nach/etc/pylintrc und ~/.pylintrc. Die Option --generate-rcfile generiert eine kommentierte Konfigurationsdatei gemäß der aktuellen Konfiguration auf Standard Ausgang und Ausgang. Sie können andere Optionen vor diesem setzen, um sie in der Konfiguration zu verwenden, oder mit den Standardwerten beginnen und die Konfiguration manuell einstellen.

3

Kommentar über paxdiablo Antwort - wie ich es nicht direkt genug Ruf Kommentar: - der Anzahl Bezug/

Ich mag es nicht, die sybolic Name viel ausdrucksstärker und vermeiden hinzufügen zu müssen ein Kommentar, der im Laufe der Zeit obsolet werden könnte.

Also würde ich lieber tun:

#pylint: disable-msg=too-many-arguments 

Und ich würde auch dort baumeln empfehlen es nicht zu verlassen: Es wird aktiv bleiben, bis die Datei endet oder es deaktiviert ist, je nachdem, was zuerst eintritt.

Also besser tun:

#pylint: disable-msg=too-many-arguments 
code_which_would_trigger_the_msg 
#pylint: enable-msg=too-many-arguments  

ich auch eine pro Zeile einzelne Warnung/Fehler Aktivierung/Deaktivierung würde empfehlen.

Verwandte Themen