wake-up-neo.com

Warum wird die Verwendung von len (SEQUENCE) in Bedingungswerten von Pylint als falsch angesehen?

Betrachtet man diesen Codeausschnitt:

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 Nachricht bezüglich der Zeile mit der if-Anweisung alarmiert:

[Pylint] C1801: Verwenden Sie nicht len(SEQUENCE) als Bedingungswert

Die Regel C1801 klang für mich auf den ersten Blick nicht sehr vernünftig, und die Definition im Referenzhandbuch erklärt nicht, warum dies ein Problem ist. Tatsächlich nennt es geradezu eine falsche Verwendung .

len-as-condition (C1801) : len(SEQUENCE) nicht als Bedingungswert verwenden Wird verwendet, wenn Pylint eine falsche Erkennung vornimmt Verwendung von len (Sequenz) innerhalb von Bedingungen.

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 dass __len__ auf Nebenwirkungen programmiert werden kann, aber es ist fraglich, ob dies allein für Pylint problematisch genug ist, eine solche Verwendung als falsch zu bezeichnen. Bevor ich mein Projekt einfach so konfiguriere, dass es die Regel ignoriert, möchte ich wissen, ob ich etwas in meiner Argumentation vermisse.

Wann ist die Verwendung von len(SEQ) als Bedingungswert problematisch? Welche wichtigen Situationen versucht Pylint mit C1801 zu vermeiden?

182
E_net4

Wann ist die Verwendung von len(SEQ) als Bedingungswert problematisch? Welche wichtigen Situationen versucht Pylint mit C1801 zu vermeiden?

Es ist nicht wirklich problematisch, len(SEQUENCE) zu verwenden - obwohl es möglicherweise nicht so effizient ist (siehe Kommentar von chepner ). Unabhängig davon überprüft Pylint den Code auf Übereinstimmung mit dem PEP 8 Style Guide , in dem dies angegeben ist

Verwenden Sie für Sequenzen (Strings, Listen, Tupel) die Tatsache, dass leere Sequenzen falsch sind.

Yes: if not seq:
     if seq:

No:  if len(seq):
     if not len(seq):

Als 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 Sequenz in einem Booleschen Kontext zu False ausgewertet wird, wird jedoch als „pythonischer“ angesehen.

244

Beachten Sie, dass bei der Verwendung von NumPy-Arrays die Verwendung von len (seq) erforderlich ist (anstatt nur den bool-Wert von seq zu überprüfen).

a = numpy.array(range(10))
if a:
    print "a is not empty"

führt zu einer Ausnahme: ValueError: Der Wahrheitswert eines Arrays mit mehr als einem Element ist nicht eindeutig. Benutze a.any () oder a.all ()

Daher ist die C1801-Nachricht für Code, der sowohl Python -Listen als auch NumPy-Arrays verwendet, weniger hilfreich.

35
Cameron Hayne

Die nächste Version von Pylint sollte sich nicht mehr unnötig beschweren, nachdem https://github.com/PyCQA/pylint/issues/2684 und https://github.com/PyCQA/pylint/ Ausgaben/1405

Vielen Dank an PaulRenvoise , PCManticore und adhearn für ihre Arbeit an der Behebung dieses Problems!

Zum Beispiel führt if len(files) == 0 nicht mehr dazu, dass sich Pylint beschwert.

4

Pylint scheiterte an meinem Code. Nachforschungen führten mich zu diesem Beitrag:

../filename.py:49:11: C1801: Do not use `len(SEQUENCE)` to determine if a sequence is empty (len-as-condition)
../filename.py:49:34: C1801: Do not use `len(SEQUENCE)` to determine if a sequence is empty (len-as-condition)

Dies war mein Code vor:

def list_empty_folders(directory):
"""The Module Has Been Build to list empty Mac Folders."""
for (fullpath, dirnames, filenames) in os.walk(directory):
    if len(dirnames) == 0 and len(filenames) == 0:
        print("Exists: {} : Absolute Path: {}".format(
            os.path.exists(fullpath), os.path.abspath(fullpath)))

Das war nach meinem Code-Fix. Durch die Verwendung von int()attribute habe ich anscheinend den Pep8/Pylint erfüllt und scheint meinen Code nicht negativ zu beeinflussen:

def list_empty_folders(directory):
"""The Module Has Been Build to list empty Mac Folders."""
for (fullpath, dirnames, filenames) in os.walk(directory):
    if len(dirnames).__trunc__() == 0 and len(filenames).__trunc__() == 0:
        print("Exists: {} : Absolute Path: {}".format(
            os.path.exists(fullpath), os.path.abspath(fullpath)))

Mein Fix

Durch Hinzufügen von .__trunc__() zu der Sequenz scheint das Bedürfnis geklärt zu sein.

Ich sehe keinen Unterschied im Verhalten, aber wenn jemand Einzelheiten weiß, die mir fehlen, lassen Sie es mich bitte wissen.

0
JayRizzo