Considérant cet extrait de code:
from os import walk
files = []
for (dirpath, _, filenames) in walk(mydir):
# more code that modifies files
if len(files) == 0: # <-- C1801
return None
J'ai été alarmé par Pylint avec ce message concernant la ligne avec l'instruction if:
[pylint] C1801: Ne pas utiliser
len(SEQUENCE)
comme valeur de condition
La règle C1801, à première vue, ne me semblait pas très raisonnable et la définition du guide de référence n'explique pas pourquoi c'est un problème. En fait, il l'appelle carrément une utilisation incorrecte .
len-as-condition (C1801) : Ne pas utiliser
len(SEQUENCE)
comme valeur de condition Utilisé lorsque Pylint détecte une utilisation incorrecte de len (séquence) à l'intérieur des conditions.
Mes tentatives de recherche n'ont pas réussi non plus à me fournir une explication plus approfondie. Je comprends que la propriété de longueur d'une séquence peut être évaluée paresseusement, et cela __len__
peut être programmé pour avoir des effets secondaires, mais il est douteux que cela seul soit suffisamment problématique pour que Pylint appelle une telle utilisation incorrecte. Par conséquent, avant de simplement configurer mon projet pour ignorer la règle, je voudrais savoir si je manque quelque chose dans mon raisonnement.
Quand l'utilisation de len(SEQ)
comme valeur de condition est-elle problématique? Quelles situations majeures Pylint tente-t-il d'éviter avec le C1801?
la source
if files:
ouif not files:
len
ne connaît pas le contexte dans lequel il est appelé, donc si calculer la longueur signifie traverser la séquence entière, il le doit; il ne sait pas que le résultat est simplement comparé à 0. Le calcul de la valeur booléenne peut s'arrêter après avoir vu le premier élément, quelle que soit la durée réelle de la séquence. Je pense que pylint est un peu d'opinion ici, cependant; Je ne peux penser à aucune situation où il est mauvais d'utiliserlen
, juste que c'est une option pire que l'alternative.Réponses:
Ce n'est pas vraiment problématique à utiliser
len(SEQUENCE)
- bien qu'il ne soit pas aussi efficace (voir le commentaire de chepner ). Quoi qu'il en soit, Pylint vérifie la conformité du code avec le guide de style PEP 8 qui stipule queEn tant que programmeur Python occasionnel, qui passe d'une langue à l'autre, je considérerais la
len(SEQUENCE)
construction comme plus lisible et explicite («Explicit is better then implicit»). Cependant, l'utilisation du fait qu'une séquence vide est évaluéeFalse
dans un contexte booléen est considérée comme plus «Pythonique».la source
if len(fnmatch.filter(os.listdir(os.getcwd()), 'f_*')):
if next(iter(...), None) is not None:
(si la séquence ne peut pas contenirNone
). C'est long, mais l'len(fnmatch...)
est aussi; les deux doivent être séparés.len(s) == 0
est supérieur à mon avis est qu'il est généralisable pour d'autres types de séquences. Par exemple,pandas.Series
et les tableaux numpy.if not s:
n'est pas d'autre part, et dans ce cas, vous devrez utiliser une évaluation distincte pour tous les types possibles d'objets de type tableaux (c.-à-dpd.DataFrame.empty
.).of collections.abc
classe n'indique la__bool__
méthode. En d'autres termes, comment puis-je être sûr que je peux utiliserbool(seq)
si je sais que c'est uncollections.abc.Collection
? De plus, certaines bibliothèques affirment qu'il est interdit de vérifierbool(collection)
leurs classes.Notez que l'utilisation de len (seq) est en fait requise (au lieu de simplement vérifier la valeur booléenne de seq) lors de l'utilisation de tableaux NumPy.
entraîne une exception: ValueError: la valeur de vérité d'un tableau avec plusieurs éléments est ambiguë. Utilisez a.any () ou a.all ()
Et donc pour le code qui utilise à la fois les listes Python et les tableaux NumPy, le message C1801 est loin d'être utile.
la source
Il s'agissait d'un problème dans Pylint, et il ne considère plus
len(x) == 0
comme incorrect.Vous ne devez pas utiliser un nu
len(x)
comme condition. Comparerlen(x)
avec une valeur explicite, comme celleif len(x) == 0
deif len(x) > 0
est tout à fait correct et n'est pas interdit par PEP 8.Depuis PEP 8 :
Notez que le test explicite de la longueur n'est pas interdit. Le Zen de Python déclare:
Dans le choix entre
if not seq
etif not len(seq)
, les deux sont implicites mais le comportement est différent. Maisif len(seq) == 0
ouif len(seq) > 0
sont des comparaisons explicites et dans de nombreux contextes le comportement correct.Dans pylint, PR 2815 a corrigé ce bogue, signalé pour la première fois sous le numéro 2684 . Il continuera de se plaindre
if len(seq)
, mais il ne se plaindra plusif len(seq) > 0
. Le PR a été fusionné 2019-03-19, donc si vous utilisez pylint 2.4 (publié le 2019-09-14), vous ne devriez pas voir ce problème.la source
Pylint échouait pour mon code et la recherche m'a conduit à ce poste:
C'était mon code avant:
C'était après ma correction de code. En utilisant le
int()
attribute
, je semble avoir satisfait le Pep8 / Pylint et ne semble pas avoir un impact négatif sur mon code:My Fix
En ajoutant
.__trunc__()
à la séquence, il semble avoir réglé le besoin.Je ne vois pas de différence dans le comportement, mais si quelqu'un connaît les détails qui me manquent, faites-le moi savoir.
la source
__trunc__()
la sortie delen(seq)
, qui tronque (quelque peu de manière redondante) la valeur de longueur en un entier. Il ne fait que «feindre» la charpie sans aborder la raison derrière elle. La suggestion de la réponse acceptée n'a-t-elle pas fonctionné pour vous?this worked for me
, même si ce n'est pas tout à fait approprié. Mais, pour clarifier même si c'est redondant si vous faites une comparaison len (seq) == 0, trunc ne devrait rien avoir à faire car ils sont déjà des entiers. droite?__trunc__()
ne fait rien de significatif. Notez que je n'ai pas fait référence à la comparaison comme étant redondante, mais à cette tentative de tronquer la longueur. L'avertissement disparaît uniquement car il n'attend qu'une expression du formulairelen(seq) == 0
. Je crois que la charpie dans ce cas s'attendrait à ce que vousif not dirnames and not filenames:
__bool__
fonction n'est pas définie dans la séquence sous-jacente.