与空列表比较时使用“==”运算符是错误的吗?

时间:2015-05-10 03:31:18

标签: python list pycharm pep8

当我使用==运算符与空列表进行比较时,PyCharm(4.0.6)会抱怨,但是当我使用is运算符时它不会出现:

enter image description here

我想这与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做错了什么?

1 个答案:

答案 0 :(得分:23)

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

  

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

Yes: if not seq:
     if seq:

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

由于空序列在Python中是假的,

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

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

注意:如果两个值相等,则不应使用is进行比较,因为is运算符会检查两个对象是否相同,但是{{1检查两个对象是否相等。

我挖掘了源代码以弄清楚发生了什么。当我们==时,

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

我们试图看看当前的序列是否可以是Truthy。这内部检查序列的长度是否为零(这只是一个简单的查找,因为列表的长度是在变量中维护的)。如果长度为零,那么>>> 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 将是Truthy。这里我们不构造一个新的列表,但我们只是隐式地检查长度,而不是显式地执行

if not actions:

所以,我猜测Python Gurus建议if len(actions) == 0: ,因为它也有性能优势。