问题:为什么Pylint认为在条件值中使用len(SEQUENCE)不正确?
考虑以下代码片段:
from os import walk
files = []
for (dirpath, _, filenames) in walk(mydir):
# more code that modifies files
if len(files) == 0: # <-- C1801
return None
Pylint使我对有关if语句行的消息感到震惊:
[pylint] C1801:请勿
len(SEQUENCE)
用作条件值
乍一看,规则C1801在我看来并不十分合理,参考指南中的定义也无法解释为什么这是一个问题。实际上,它彻头彻尾地称其为不正确的用法。
len-as-condition(C1801): 不要
len(SEQUENCE)
用作条件值当Pylint检测到内部条件不正确使用len(sequence)时使用。
我的搜索尝试也未能为我提供更深入的解释。我确实知道,序列的length属性可能会被延迟评估,并且__len__
可以编程为具有副作用,但是令人怀疑的是,仅此一个问题是否足以使Pylint认为这种用法不正确。因此,在我简单地将项目配置为忽略规则之前,我想知道我的推理中是否缺少某些内容。
什么时候将len(SEQ)
用作条件值有问题?Pylint尝试使用C1801避免哪些主要情况?
回答 0
什么时候将
len(SEQ)
用作条件值有问题?Pylint尝试使用C1801避免哪些主要情况?
使用它并不是真的有问题len(SEQUENCE)
-尽管它可能没有效率那么高(请参阅chepner的评论)。无论如何,Pylint会检查代码是否符合PEP 8样式指南,该指南指出
对于序列(字符串,列表,元组),请使用空序列为假的事实。
Yes: if not seq: if seq: No: if len(seq): if not len(seq):
作为偶尔在各种语言之间徘徊的Python程序员,我认为该len(SEQUENCE)
结构更具可读性和显式性(“显式优于隐式”)。但是,使用空序列False
在布尔上下文中求值的事实被认为更“ Pythonic”。
回答 1
请注意,使用NumPy数组时,实际上需要使用len(seq)(而不是仅检查seq的bool值)。
a = numpy.array(range(10))
if a:
print "a is not empty"
导致异常:ValueError:具有多个元素的数组的真值不明确。使用a.any()或a.all()
因此,对于同时使用Python列表和NumPy数组的代码,C1801消息的用处不大。
回答 2
这是pylint中的问题,并且不再视为len(x) == 0
不正确。
您不应以裸露 len(x)
为条件。比较len(x)
反对一个明确的值,如if len(x) == 0
中if len(x) > 0
是PEP 8完全正常和不禁止。
从PEP 8:
# Correct: if not seq: if seq: # Wrong: if len(seq): if not len(seq):
显式胜于隐式。
在这两者之间的选择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发布),则不应看到此问题。
回答 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)))
这是我的代码修复之后。通过使用int()
attribute
,我似乎对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__()
顺序,似乎已经解决了需求。
我的行为没有区别,但是如果有人知道我所缺少的细节,请告诉我。