考虑以下代码片段:

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): 当Pylint检测到条件中不正确使用len(SEQUENCE)时使用。

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

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


当前回答

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

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

PEP 8:

#正确: 如果不是seq: 如果seq: #错误: 如果len (seq): 如果不是len(seq):

注意,不禁止显式地测试长度。Python的禅意是:

显性比隐性好。

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

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

其他回答

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

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

对于序列(字符串、列表、元组),使用空序列为假的事实。 是:如果没有seq: 如果seq: 否:if len(seq): 如果不是len(seq):

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

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()属性,我似乎已经满足了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) == 0或if len(x) > 0是完全可以的,PEP 8不禁止。

PEP 8:

#正确: 如果不是seq: 如果seq: #错误: 如果len (seq): 如果不是len(seq):

注意,不禁止显式地测试长度。Python的禅意是:

显性比隐性好。

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

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

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