Учитывая этот фрагмент кода:
from os import walk
files = []
for (dirpath, _, filenames) in walk(mydir):
# more code that modifies files
if len(files) == 0: # <-- C1801
return None
Пилинт встревожил меня этим сообщением относительно строки с оператором if:
[pylint] C1801: не использовать в
len(SEQUENCE)
качестве значения условия
Правило C1801, на первый взгляд, показалось мне не очень разумным, и определение в справочном руководстве не объясняет, почему это проблема. Фактически, это прямо называет это неправильным использованием .
len-as-condition (C1801) : Не использовать в
len(SEQUENCE)
качестве значения условия. Используется, когда Pylint обнаруживает неправильное использование len (последовательности) внутри условий.
Мои попытки поиска также не дали мне более глубокого объяснения. Я понимаю, что свойство длины последовательности может быть лениво оценено, и это __len__
может быть запрограммировано, чтобы иметь побочные эффекты, но сомнительно, является ли это само по себе достаточно проблематичным для Pylint, чтобы назвать такое использование неправильным. Следовательно, прежде чем я просто настрою свой проект на игнорирование правила, я хотел бы знать, что я что-то упускаю в своих рассуждениях.
Когда использование len(SEQ)
в качестве значения условия проблематично? Каких основных ситуаций Pylint пытается избежать с помощью C1801?
источник
if files:
илиif not files:
len
не знает контекст, в котором он вызывается, поэтому, если вычисление длины означает пересечение всей последовательности, оно должно; он не знает, что результат просто сравнивается с 0. Вычисление логического значения может прекратиться после того, как он увидит первый элемент, независимо от того, какова длина последовательности на самом деле. Я думаю, что Пилинт здесь немного самоуверен; Я не могу придумать ни одной ситуации, когда это неправильно использоватьlen
, просто что это худший вариант, чем альтернатива.Ответы:
Это не очень проблематично в использовании
len(SEQUENCE)
- хотя это может быть не так эффективно (см . Комментарий Чепнера ). В любом случае, Pylint проверяет код на соответствие руководству по стилю PEP 8, в котором говорится, чтоБудучи случайным программистом на Python, который переключается между языками, я считаю
len(SEQUENCE)
конструкцию более читаемой и явной («Явное лучше, чем неявное»). Однако использование того факта, что пустая последовательность оцениваетсяFalse
в логическом контексте, считается более «питоническим».источник
if len(fnmatch.filter(os.listdir(os.getcwd()), 'f_*')):
if next(iter(...), None) is not None:
(если последовательность не может содержатьNone
). Это долго, ноlen(fnmatch...)
слишком долго; оба должны быть разделены.len(s) == 0
мой взгляд, лучше, заключается в том, что она обобщаема для других типов последовательностей. Например,pandas.Series
и NumPy массивов.if not s:
с другой стороны, и в этом случае вам нужно будет использовать отдельную оценку для всех возможных типов объектов, подобных массивам (то естьpd.DataFrame.empty
).of collections.abc
класс не заявляет__bool__
метод. Другими словами, как я могу быть уверен, что я могу использовать,bool(seq)
если я знаю, что этоcollections.abc.Collection
? Более того, некоторые библиотеки заявляют, что запрещается проверятьbool(collection)
их классы.Обратите внимание, что на самом деле требуется использование len (seq) (вместо простой проверки значения bool seq) при использовании массивов NumPy.
приводит к исключению: ValueError: Значение истинности массива с более чем одним элементом является неоднозначным. Используйте a.any () или a.all ()
И, следовательно, для кода, который использует как списки Python, так и массивы NumPy, сообщение C1801 менее чем полезно.
источник
Это была проблема в Pylint, и она больше не считается
len(x) == 0
неправильной.Вы не должны использовать голое
len(x)
как условие. Сравнениеlen(x)
с явным значением, таким какif len(x) == 0
ofif len(x) > 0
, совершенно нормально и не запрещено PEP 8.Из ППК 8 :
Обратите внимание, что явное тестирование длины не запрещено. Дзен Python гласит:
В выборе между
if not seq
иif not len(seq)
, оба являются неявными, но поведение отличается. Ноif len(seq) == 0
илиif len(seq) > 0
явные сравнения и во многих контекстах правильное поведение.В pylint PR 2815 исправил эту ошибку, впервые сообщенную как проблема 2684 . Он будет продолжать жаловаться
if len(seq)
, но больше не будет жаловатьсяif len(seq) > 0
. PR был объединен 2019-03-19, поэтому, если вы используете Pylint 2.4 (выпущен 2019-09-14), вы не должны видеть эту проблему.источник
Pylint терпел неудачу для моего кода, и исследование привело меня к этому сообщению:
Это был мой код раньше:
Это было после исправления моего кода. Используя
int()
attribute
, я, кажется, удовлетворил Pep8 / Pylint и, похоже, не оказывает негативного влияния на мой код:Мое исправление
Добавляя
.__trunc__()
к последовательности, кажется, что она исчерпала потребность.Я не вижу различий в поведении, но если кто-то знает особенности, которые мне не хватает, пожалуйста, дайте мне знать.
источник
__trunc__()
выводlen(seq)
, который (несколько избыточно) усекает значение длины до целого числа. Он только «финтирует» пух, не обращаясь к причине, стоящей за этим. Разве предложение в принятом ответе не сработало для вас?this worked for me
, даже если это не совсем уместно. Но, чтобы уточнить, даже если это избыточно, если вы выполняете сравнение len (seq) == 0, trunc не должен ничего делать, так как он уже является целым числом. право?__trunc__()
не делает ничего значащего. Обратите внимание, что я ссылался не на сравнение как на избыточное, а на попытку урезания длины. Предупреждение исчезает только потому, что ожидает только выражение формыlen(seq) == 0
. Я полагаю, что в этом случае ожидается, что вы замените оператор if следующим:if not dirnames and not filenames:
__bool__
функция не определена в основной последовательности.