Почему использование len (SEQUENCE) в значениях условий считается неправильным Pylint?
Учитывая этот фрагмент кода:
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__
можно запрограммировать на наличие побочных эффектов, но сомнительно, достаточно ли это достаточно для того, чтобы Пилинт назвал такое использование неправильным. Следовательно, прежде чем я просто сконфигурирую свой проект на игнорирование правила, я хотел бы знать, не хватает ли я чего-то в своих рассуждениях.
Когда использование len(SEQ)
в качестве значения условия проблематично? Какие основные ситуации Pylint пытается избежать с помощью C1801?
Ответы
Ответ 1
Когда использование len(SEQ)
в качестве значения условия проблематично? Какие основные ситуации Pylint пытается избежать с C1801?
Не очень проблематично использовать len(SEQUENCE)
- хотя это может быть не так эффективно (см. комментарий для чатов). Несмотря на это, Pylint проверяет код на соответствие руководству по стилю PEP 8, в котором говорится, что
Для последовательностей (строки, списки, кортежи) используйте тот факт, что пустые последовательности являются ложными.
Yes: if not seq:
if seq:
No: if len(seq):
if not len(seq):
Как случайный программист на языке Python, который перемещается между языками, Id рассматривает конструкцию len(SEQUENCE)
как более читаемую и явную ( "Явный лучше, чем неявный" ). Однако использование того факта, что пустая последовательность оценивается как False
в булевом контексте, считается более "Pythonic".
Ответ 2
Обратите внимание, что использование len (seq) на самом деле требуется (вместо проверки значения bool seq) при использовании массивов NumPy.
a = numpy.array(range(10))
if a:
print "a is not empty"
приводит к исключению:
ValueError: Значение истины массива с более чем одним элементом неоднозначно. Используйте a.any() или a.all()
И, следовательно, для кода, который использует как списки Python, так и массивы NumPy, сообщение C1801 менее полезно.
Ответ 3
Pylint терпел неудачу для моего кода, и исследование привело меня к этому сообщению:
../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)
Это был мой код раньше:
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)))
Это было после исправления моего кода. Используя attribute
int()
, я, кажется, удовлетворил Pep8/Pylint и, похоже, не оказывает негативного влияния на мой код:
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)))
Мое исправление
Добавив .__trunc__()
к последовательности, она, похоже, исчерпала необходимость.
Я не вижу различий в поведении, но если кто-то знает особенности, которые мне не хватает, пожалуйста, дайте мне знать.
Ответ 4
В следующей версии Pylint больше не нужно пожаловаться после исправления https://github.com/PyCQA/pylint/issues/2684 и https://github.com/PyCQA/pylint/issues/1405
Спасибо PaulRenvoise, PCManticore и adhearn за их работу по исправлению этой ошибки !
Например, if len(files) == 0
больше не вызывает жалобу Pylint.