考虑以下代码片段:
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在我的代码中失败了,研究让我看到了这篇文章:
../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日)或更新版本,应该不会看到此问题。