In Anbetracht dieses Code-Snippets:
from os import walk
files = []
for (dirpath, _, filenames) in walk(mydir):
# more code that modifies files
if len(files) == 0: # <-- C1801
return None
Ich wurde von Pylint mit dieser Meldung bezüglich der Zeile mit der if-Anweisung alarmiert:
[pylint] C1801: Nicht verwenden
len(SEQUENCE)
als Bedingungswert verwenden
Die Regel C1801 klang auf den ersten Blick für mich nicht sehr vernünftig, und die Definition im Referenzhandbuch erklärt nicht, warum dies ein Problem ist. Tatsächlich nennt es es geradezu eine falsche Verwendung .
len-as-condition (C1801) : Nicht
len(SEQUENCE)
als Bedingungswert verwenden Wird verwendet, wenn Pylint eine falsche Verwendung von len (Sequenz) innerhalb von Bedingungen feststellt.
Meine Suchversuche haben mir auch keine tiefere Erklärung geliefert. Ich verstehe, dass die Längeneigenschaft einer Sequenz möglicherweise träge ausgewertet wird und __len__
so programmiert werden kann, dass sie Nebenwirkungen hat, aber es ist fraglich, ob dies allein für Pylint problematisch genug ist, um eine solche Verwendung als falsch zu bezeichnen. Bevor ich mein Projekt einfach so konfiguriere, dass die Regel ignoriert wird, möchte ich wissen, ob mir etwas in meiner Argumentation fehlt.
Wann ist die Verwendung len(SEQ)
als Bedingungswert problematisch? Welche wichtigen Situationen versucht Pylint mit C1801 zu vermeiden?
quelle
if files:
oderif not files:
len
kennt den Kontext, in dem es aufgerufen wird, nicht. Wenn das Berechnen der Länge das Durchlaufen der gesamten Sequenz bedeutet, muss es; Es ist nicht bekannt, dass das Ergebnis nur mit 0 verglichen wird. Die Berechnung des Booleschen Werts kann beendet werden, nachdem das erste Element angezeigt wurde, unabhängig davon, wie lang die Sequenz tatsächlich ist. Ich denke, Pylint ist hier allerdings ein bisschen eigensinnig; Ich kann mir keine Situation vorstellen, in der die Verwendung falsch istlen
, nur dass es eine schlechtere Option als die Alternative ist.Antworten:
Die Verwendung ist nicht wirklich problematisch
len(SEQUENCE)
- obwohl sie möglicherweise nicht so effizient ist (siehe chepners Kommentar ). Unabhängig davon überprüft Pylint den Code auf Übereinstimmung mit dem PEP 8- Styleguide , in dem dies angegeben istAls gelegentlicher Python-Programmierer, der zwischen Sprachen wechselt, würde ich das
len(SEQUENCE)
Konstrukt als lesbarer und expliziter betrachten („Explizit ist besser als implizit“). Die Verwendung der Tatsache, dass eine leere SequenzFalse
in einem booleschen Kontext ausgewertet wird, wird jedoch als „pythonischer“ angesehen.quelle
if len(fnmatch.filter(os.listdir(os.getcwd()), 'f_*')):
if next(iter(...), None) is not None:
(wenn die Sequenz nicht enthalten kannNone
). Das ist lang, aber daslen(fnmatch...)
ist auch lang; beide müssen aufgeteilt werden.len(s) == 0
meiner Meinung nach überlegen ist, ist, dass es für andere Arten von Sequenzen verallgemeinerbar ist. Zum Beispielpandas.Series
und numpy Arrays.if not s:
ist nicht auf der anderen Seite, und in diesem Fall müssten Sie eine separate Auswertung für alle möglichen Arten von Arrays-ähnlichen Objekten (dhpd.DataFrame.empty
) verwenden.of collections.abc
Klasse die__bool__
Methode an. Mit anderen Worten, wie kann ich sicher sein, dass ich es verwenden kann,bool(seq)
wenn ich weiß, dass es ein istcollections.abc.Collection
? Moreso, einige Bibliotheken erklären, dass es verboten ist,bool(collection)
nach ihren Klassen zu suchen .Beachten Sie, dass bei Verwendung von NumPy-Arrays tatsächlich die Verwendung von len (seq) erforderlich ist (anstatt nur den Bool-Wert von seq zu überprüfen).
führt zu einer Ausnahme: ValueError: Der Wahrheitswert eines Arrays mit mehr als einem Element ist nicht eindeutig. Verwenden Sie a.any () oder a.all ()
Für Code, der sowohl Python-Listen als auch NumPy-Arrays verwendet, ist die Nachricht C1801 daher weniger hilfreich.
quelle
Dies war ein Problem bei Pylint und wird nicht mehr
len(x) == 0
als falsch angesehen.Sie sollten kein Bare
len(x)
als Bedingung verwenden. Vergleichenlen(x)
mit einem expliziten Wert wieif len(x) == 0
vonif len(x) > 0
ist völlig in Ordnung und wird von PEP 8 nicht verboten.Aus PEP 8 :
Beachten Sie, dass das explizite Testen der Länge nicht verboten ist. Das Zen von Python besagt:
Bei der Wahl zwischen
if not seq
undif not len(seq)
sind beide implizit, aber das Verhalten ist unterschiedlich. Aberif len(seq) == 0
oderif len(seq) > 0
sind explizite Vergleiche und in vielen Zusammenhängen das richtige Verhalten.In Pylint hat PR 2815 diesen Fehler behoben, der zuerst als Problem 2684 gemeldet wurde . Es wird sich weiterhin beschweren
if len(seq)
, aber es wird sich nicht mehr beschwerenif len(seq) > 0
. Die PR wurde am 19.03.2019 zusammengeführt. Wenn Sie also Pylint 2.4 (veröffentlicht am 14.09.2019) verwenden, sollte dieses Problem nicht auftreten.quelle
Pylint versagte bei meinem Code und die Recherche führte mich zu diesem Beitrag:
Dies war mein Code vor:
Dies war nach meinem Code-Fix. Durch die Verwendung von
int()
attribute
scheint ich den Pep8 / Pylint zufrieden zu stellen und habe keinen negativen Einfluss auf meinen Code:Mein Fix
Durch das Hinzufügen
.__trunc__()
zur Sequenz scheint der Bedarf gedeckt zu sein.Ich sehe keinen Unterschied im Verhalten, aber wenn jemand Einzelheiten weiß, die mir fehlen, lassen Sie es mich bitte wissen.
quelle
__trunc__()
die Ausgabe von auflen(seq)
, die (etwas redundant) den Längenwert auf eine Ganzzahl abschneidet. Es "täuscht" nur die Flusen, ohne den Grund dafür anzusprechen. Hat der Vorschlag in der akzeptierten Antwort nicht für Sie funktioniert?this worked for me
auch wenn es nicht ganz angemessen ist. Um zu verdeutlichen, auch wenn es redundant ist, wenn Sie einen len (seq) == 0-Vergleich durchführen, sollte trunc nichts tun müssen, da es sich bereits um Ganzzahlen handelt. richtig?__trunc__()
macht nichts Sinnvolles. Beachten Sie, dass ich den Vergleich nicht als redundant bezeichnet habe, sondern auf diesen Versuch, die Länge zu kürzen. Die Warnung verschwindet nur, weil sie nur einen Ausdruck des Formulars erwartetlen(seq) == 0
. Ich glaube, dass die Flusen in diesem Fall erwarten würden, dass Sie die if-Anweisung durch die folgende ersetzen:if not dirnames and not filenames:
__bool__
Funktion nicht in der zugrunde liegenden Sequenz definiert ist.