【问题标题】:Is it wrong to use the "==" operator when comparing to an empty list? [duplicate]与空列表比较时使用“==”运算符是否错误? [复制]
【发布时间】:2015-07-20 18:18:11
【问题描述】:

当我使用 == 运算符与空列表进行比较时,PyCharm (4.0.6) 会报错,但当我使用 is 运算符时不会报错:

我猜这与 PEP 8 有关,但问题是当我使用 is 运算符时,正如 PyCharm 所建议的那样,我有一个误报。这是 iPython shell 中的一个简单示例,表明在这种情况下 == 运算符似乎更合适,因为 is 运算符返回一个假阴性:

In[2]: actions = []
In[3]: actions == []
Out[3]: True
In[4]: actions is []
Out[4]: False

有人能解释一下为什么 PyCharm 在与空列表进行比较时会抱怨 == 运算符吗?根据 PEP 8,我做错了吗?

【问题讨论】:

  • == 没有错误,它只是暗示有更好的方法。
  • 使用== 运算符似乎更明确,但它会强制类型区分。由于 Python 是“鸭子类型”,我想这就是为什么他们提供了一个单一的解决方案来检查序列是否为空。使用if seq: 适用于列表、字符串、元组和字典。
  • 如果有人觉得它有用,我创建了一个 youtube 教程,讨论 '==' 运算符并比较检查列表是否为空的不同方法youtube.com/watch?v=8V88bl3tuBQ

标签: python list pycharm pep8


【解决方案1】:

引用PEP-8's Programming Recommendations 部分,

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

Yes: if not seq:
     if seq:

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

由于空序列在 Python 中是 Falsy,

>>> bool([])
False
>>> bool(())
False

您可以简单地使用 PEP-8 中提到的if not

注意:永远不要使用is 来比较两个值是否相等,因为is 运算符会检查两个对象是否相同,但== 会检查两个对象是否相同是平等的。


我深入研究了源代码以弄清楚发生了什么。当我们做a == []

>>> dis(compile('if a == []: pass', "string", "exec"))
  1           0 LOAD_NAME                0 (a)
              3 BUILD_LIST               0
              6 COMPARE_OP               2 (==)
              9 POP_JUMP_IF_FALSE       15
             12 JUMP_FORWARD             0 (to 15)
        >>   15 LOAD_CONST               0 (None)
             18 RETURN_VALUE

我们正在构建一个新列表,这将是一个非常昂贵的操作,仅用于比较。另一方面

>>> dis(compile('if not a: pass', "string", "exec"))
  1           0 LOAD_NAME                0 (a)
              3 POP_JUMP_IF_TRUE         9
              6 JUMP_FORWARD             0 (to 9)
        >>    9 LOAD_CONST               0 (None)
             12 RETURN_VALUE

我们正在尝试查看当前序列是否可能是真实的。这在内部检查序列的长度是否为零(这只是一个简单的查找,因为列表的长度保存在一个变量中)。如果长度为零,则 if not actions: 将是 Truthy。这里我们没有构造一个新的列表,只是隐式地检查长度,而不是显式地做

if len(actions) == 0:

所以,我猜 Python 大师建议 if not seq,因为它也可能具有性能优势。

【讨论】:

  • 但这似乎不是“pythonic”的编码方式。与空列表进行显式比较对我来说似乎更具可读性。错了吗?
  • @renatov:我怀疑 Guido、Tim 和 Barry 比你更了解 Python 是什么,但如果你不同意,请尝试让 Python 社区相信 PEP 8 需要改变。
  • @abarnert 如果该示例准确地显示了所问的问题,则该论点将具有更大的权重,对我来说,这是检查空列表的最直接和自然的方法,而不是检查长度。
  • @MarkRansom:我认为很明显,其意图不是“if not seq: 仍然很糟糕,但我们将其列为“是”只是为了说明if len(seq): 真的很糟糕” .但是人们已经被它之前没有提到if seq != ''的事实弄糊涂了,人们可能会再次感到困惑。也许应该改进 PEP 8 以使意图更清晰。
  • @renatov:更重要的是,thefourtheye 向您展示了 PEP 8 说 if not seq: 是肯定的。这就是你要求的答案。如果您不是在争论 PEP 8 是错误的,那么您在说什么?您是在询问该决定背后的理由,还是在讨论它的地方?如果是这样,这是一个非常好的问题(尽管对于 SO 来说不一定是一个好问题),但这不是您最初的问题,因此在 cmets 中将其作为后续问题并不是获得答案的方法。
【解决方案2】:

根据 PEP8 文档,您应该使用

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)

【讨论】:

    猜你喜欢
    • 2021-08-02
    • 2017-07-21
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 2011-03-10
    • 2018-12-23
    • 1970-01-01
    相关资源
    最近更新 更多