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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43121340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 22:32:32  来源:igfitidea点击:

Why is the use of len(SEQUENCE) in condition values considered incorrect by Pylint?

pythonconditionalpylint

提问by E_net4 the Rustacean

Considering this code snippet:

考虑这个代码片段:

from os import walk

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

I was alarmed by Pylint with this message regarding the line with the if statement:

我对 Pylint 的这条消息感到震惊,该消息与 if 语句的行有关:

[pylint] C1801:Do not use len(SEQUENCE)as condition value

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

The rule C1801, at first glance, did not sound very reasonable to me, and the definition on the reference guidedoes not explain why this is a problem. In fact, it downright calls it an incorrect use.

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

len-as-condition (C1801): Do not use len(SEQUENCE)as condition value Used when Pylint detects incorrect use of len(sequence) inside conditions.

len-as-condition (C1801): 不要len(SEQUENCE)用作条件值 当 Pylint 检测到不正确使用 len(sequence) 条件时使用。

My search attempts have also failed to provide me a deeper explanation. I do understand that a sequence's length property may be lazily evaluated, and that __len__can be programmed to have side effects, but it is questionable whether that alone is problematic enough for Pylint to call such a use incorrect. Hence, before I simply configure my project to ignore the rule, I would like to know whether I am missing something in my reasoning.

我的搜索尝试也未能为我提供更深入的解释。我确实理解序列的长度属性可能会被懒惰地评估,并且__len__可以对其进行编程以产生副作用,但是仅凭这一点是否就足以让 Pylint 认为这种使用不正确,这是值得怀疑的。因此,在我简单地将我的项目配置为忽略规则之前,我想知道我的推理中是否遗漏了什么。

When is the use of len(SEQ)as a condition value problematic? What major situations is Pylint attempting to avoid with C1801?

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

回答by Anthony Geoghegan

When is the use of len(SEQ)as a condition value problematic? What major situations is Pylint attempting to avoid with C1801?

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

It's not reallyproblematic to use len(SEQUENCE)– though it may not be as efficient (see chepner's comment). Regardless, Pylint checks code for compliance with the PEP 8 style guidewhich states that

使用起来并不是真的有问题len(SEQUENCE)——尽管它可能效率不高(参见chepner 的评论)。无论如何,Pylint 检查代码是否符合PEP 8 风格指南,其中指出

For sequences, (strings, lists, tuples), use the fact that empty sequences are false.

Yes: if not seq:
     if seq:

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

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

Yes: if not seq:
     if seq:

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

As an occasional Python programmer, who flits between languages, I'd consider the len(SEQUENCE)construct to be more readable and explicit (“Explicit is better then implicit”). However, using the fact that an empty sequence evaluates to Falsein a Boolean context is considered more “Pythonic”.

作为偶尔在语言之间穿梭的 Python 程序员,我认为该len(SEQUENCE)构造更具可读性和明确性(“显式优于隐式”)。然而,False在布尔上下文中使用空序列计算结果被认为更“Pythonic”。

回答by Cameron Hayne

Note that the use of len(seq) is in fact required (instead of just checking the bool value of seq) when using NumPy arrays.

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

a = numpy.array(range(10))
if a:
    print "a is not empty"

results in an exception: ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

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

And hence for code that uses both Python lists and NumPy arrays, the C1801 message is less than helpful.

因此,对于同时使用 Python 列表和 NumPy 数组的代码,C1801 消息的帮助不大。

回答by gerrit

This was a issue in pylint, and it no longer considers len(x) == 0as incorrect.

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

You should not use a barelen(x)as a condition. Comparing len(x)against an explicit value, such as if len(x) == 0of if len(x) > 0is totally fine and not prohibited by PEP 8.

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

From PEP 8:

PEP 8

# Correct:
if not seq:
if seq:

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

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

Note that explicitly testing for the lengthis not prohibited. The Zen of Pythonstates:

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

Explicit is better than implicit.

显式优于隐式。

In the choice between if not seqand if not len(seq), both are implicit but behaviour is different. But if len(seq) == 0or if len(seq) > 0are explicit comparisons and in many contexts the correct behaviour.

在这两者之间的选择if not seqif not len(seq),无一不是隐含的,而行为是不同的。但是if len(seq) == 0orif len(seq) > 0是明确的比较,并且在许多情况下是正确的行为。

In pylint, PR 2815has fixed this bug, first reported as issue 2684. It will continue to complain about if len(seq), but it will no longer complain about if len(seq) > 0. The PR was merged 2019-03-19 so if you are using pylint 2.4 (released 2019-09-14) you should not see this problem.

在 pylint 中,PR 2815已经修复了这个错误,首先报告为问题 2684。它会继续抱怨if len(seq),但它不会再抱怨if len(seq) > 0。PR 已于 2019-03-19 合并,因此如果您使用的是 pylint 2.4(2019-09-14 发布),则不应看到此问题。

回答by JayRizzo

Pylint was failing for my code and research led me to this post:

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)

This was my code before:

这是我之前的代码:

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)))

This was after my code fix. By using the int()attribute, I seem to have satisfied the Pep8/Pylint and doesn't seem to have a negative impact on my code:

这是在我的代码修复之后。通过使用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)))

My Fix

我的修复

By adding .__trunc__()to the sequence it seems to have settled the need.

通过添加.__trunc__()序列,它似乎满足了需求。

I do not see a difference in the behaviour, but if anyone knows specifics that I am missing, please let me know.

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