关于python:与空列表比较时使用”==”运算符是否错误?

Is it wrong to use the “==” operator when comparing to an empty list?

本问题已经有最佳答案,请猛点这里访问。

Pycharm(4.0.6)在使用==运算符与空列表进行比较时会抱怨,但在使用is运算符时不会抱怨:

enter image description here

我想这与PEP8有关,但问题是,正如Pycharm所说,当我使用is操作符时,我有一个错误的否定。下面是ipython shell中的一个简单示例,说明在这种情况下,==运算符似乎更合适,因为is运算符返回一个假负:

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

有人能解释一下为什么与空名单相比,Pycharm会抱怨==操作符吗?根据PEP 8,我做错什么了吗?


引用PEP-8的编程建议部分,

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

1
2
3
4
5
Yes: if not seq:
     if seq:

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

因为空序列在python中是不稳定的,

1
2
3
4
>>> bool([])
False
>>> bool(())
False

如PEP-8所述,您只需使用if not

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

我深入研究了源代码以找出发生了什么。当我们做a == []时,

1
2
3
4
5
6
7
8
>>> 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

我们正在构建一个新的列表,这将是一个非常昂贵的操作,只是为了进行比较。另一方面

1
2
3
4
5
6
>>> 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:将是真实的。这里我们不构建新的列表,但是我们只是隐式地检查长度,而不是显式地检查长度。

1
if len(actions) == 0:

所以,我猜想Python专家建议使用if not seq,因为它也可能具有性能优势。


根据PEP8文件,你应该使用

1
2
3
4
5
6
7
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)