为什么在条件值中使用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

我被Pylint警告了这条关于if语句行的消息:

[pylint] C1801:不要使用len(SEQUENCE)作为条件值

规则C1801,乍一看,听起来不是很合理,参考指南上的定义没有解释为什么这是一个问题。事实上,它直接称其为不正确的使用

< p > len-as-condition (C1801): 当Pylint检测到条件中不正确使用len(sequence)时使用。

我的搜索也没能给我一个更深刻的解释。我确实理解序列的length属性可能会被惰性地求值,并且__len__可以被编程为具有副作用,但值得怀疑的是,仅这一点是否足以让Pylint认为这样的使用是不正确的。因此,在我简单地配置我的项目以忽略规则之前,我想知道我是否在推理中遗漏了一些东西。

什么时候使用len(SEQ)作为条件值有问题?Pylint试图在C1801中避免哪些主要情况?

95332 次浏览

什么时候使用len(SEQ)作为条件值有问题?什么专业 Pylint试图避免C1801的情况?< / p >

使用len(SEQUENCE)没有真的问题——尽管它可能没有那么有效(参见chepner的评论)。无论如何,Pylint检查代码是否符合PEP 8风格指南,该PEP 8风格指南声明

对于序列(字符串、列表、元组),使用空序列为假的事实。

Yes: if not seq:
if seq:


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

作为一个偶尔在不同语言之间切换的Python程序员,我认为len(SEQUENCE)构造更具可读性和显式性(“显式比隐式更好”)。然而,在布尔上下文中使用空序列求值为False这一事实被认为更“python化”。

注意,在使用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消息用处不大。

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__()添加到序列中,似乎已经解决了这一需求。

我看不出这种行为有什么不同,但如果有人知道我遗漏的细节,请告诉我。

这是Pylint中的一个问题,它不再认为len(x) == 0是不正确的。

你不应该使用裸露的 len(x)作为条件。将len(x)与显式值进行比较是完全可以的,例如if len(x) > 0if len(x) == 0, PEP 8并不禁止。

PEP 8:

# Correct:
if not seq:
if seq:


# Wrong:
if len(seq):
if not len(seq):

注意,显式地测试长度并不被禁止。Python的禅宗声明:

显性比隐性好。

if not seqif not len(seq)之间的选择中,两者都是隐式的,但行为是不同的。但是if len(seq) == 0if len(seq) > 0是显式比较,在许多情况下是正确的行为。

在Pylint中,2815年公关已经修复了这个错误,第一次报告为发行2684。它将继续报错if len(seq),但它将不再报错if len(seq) > 0。PR是在2019年3月19日合并的,所以如果您使用的是Pylint 2.4(发布于2019年9月14日)或更新版本,应该不会看到此问题。