为什么在Pylint中条件值中使用len(SEQUENCE)是不正确的?

E_n*_*ate 192 python conditional pylint

考虑此代码段:

from os import walk

files = []
for (dirpath, _, filenames) in walk(mydir):
    # more code that modifies files
if len(files) == 0: # <-- C1801
    return None
Run Code Online (Sandbox Code Playgroud)

Pylint对这条关于if语句行的消息感到震惊:

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

乍一看,规则C1801对我来说听起来不太合理,参考指南中的定义并不能解释为什么这是一个问题.事实上,它完全称之为不正确的用法.

len-as-condition(C1801): 不要len(SEQUENCE)用作条件值当Pylint在条件内检测到len(序列)的错误使用时使用.

我的搜索尝试也未能为我提供更深入的解释.我确实理解序列的长度属性可能会被懒惰地评估,并且__len__可以被编程为具有副作用,但是对于Pylint是否足以使这样的使用不正确而言,这是否有问题是值得怀疑的.因此,在我简单地配置我的项目以忽略规则之前,我想知道我的推理是否缺少某些内容.

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

Ant*_*ica 261

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

使用它并不是真正的问题len(SEQUENCE)- 虽然它可能效率不高(参见chepner的评论).无论如何,Pylint检查代码是否符合PEP 8样式指南,该指南说明了这一点

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

Yes: if not seq:
     if seq:

No:  if len(seq):
     if not len(seq):
Run Code Online (Sandbox Code Playgroud)

作为一个偶然的Python程序员,谁在语言之间徘徊,我认为这个len(SEQUENCE)结构更具可读性和显性性("明确比隐含更好").但是,使用空序列False在布尔上下文中求值的事实被认为更"Pythonic".

  • 我也是一个偶然的Python用户,我常常觉得"Pythonic方式"在它自己的模糊性中有点混乱. (9认同)
  • 只是一个普遍的问题,这些PEP建议是否可以修订?我认为'len(s)== 0'优越的另一个原因是它可以推广用于其他类型的序列。例如,`pandas.Series`和numpy数组。另一方面,if不是s:,在这种情况下,您需要对所有可能类型的类似数组的对象(即pd.DataFrame.empty)使用单独的评估。 (3认同)
  • 顺便说一句,collections.abc类中没有一个声明__bool__方法。换句话说,如果我知道它是`collections.abc.Collection`,如何确定可以使用`bool(seq)`?此外,一些库拒绝接受为它们的类检查`bool(collection)`。 (2认同)

小智 38

请注意,在使用NumPy数组时,实际上需要使用len(seq)(而不是仅仅检查seq的bool值).

a = numpy.array(range(10))
if a:
    print "a is not empty"
Run Code Online (Sandbox Code Playgroud)

导致异常:ValueError:具有多个元素的数组的真值是不明确的.使用a.any()或a.all()

因此,对于同时使用Python列表和NumPy数组的代码,C1801消息不太有用.

  • 我同意你的发言.随着[问题#1405](https://github.com/PyCQA/pylint/issues/1405)现在提出,我希望看到C1801被改造为有用的东西或者默认禁用. (4认同)
  • 另外,它对于检查序列是否具有给定数量的元素也没有用。仅在最好的情况下检查它是否完全为空才有用。 (2认同)

ger*_*rit 9

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

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

来自PEP 8

# Correct:
if not seq:
if seq:

# Wrong:
if len(seq):
if not len(seq):
Run Code Online (Sandbox Code Playgroud)

请注意,不禁止显式测试长度。Python 之禅指出:

显式的比隐式的好。

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

在 Pylint 中,PR 2815已修复此错误,首次报告为问题 2684。它会继续抱怨if len(seq),但也不会再抱怨if len(seq) > 0。PR 于 2019 年 3 月 19 日合并,因此如果您使用 Pylint 2.4(2019 年 9 月 14 日发布)或更高版本,则不应看到此问题。


Mat*_*zny 5

在修复https://github.com/PyCQA/pylint/issues/2684https://github.com/PyCQA/pylint/issues/1405之后,Pylint的下一发行版不再不必要抱怨

感谢PaulRenvoisePCManticoreadhearn为解决此问题所做的工作!

例如,if len(files) == 0将不再导致pylint抱怨。