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

ren*_*tov 28 python list pep8 pycharm

当我使用==运算符对空列表进行比较时,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
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么PyCharm ==在与空列表进行比较时会抱怨运营商吗?我是否根据PEP 8做错了什么?

the*_*eye 26

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

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

Yes: if not seq:
     if seq:

No: if len(seq)
    if not len(seq)
Run Code Online (Sandbox Code Playgroud)

由于空序列在Python中是Falsy,

>>> bool([])
False
>>> bool(())
False
Run Code Online (Sandbox Code Playgroud)

你可以简单地使用if notPEP-8中提到的.

注意: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
Run Code Online (Sandbox Code Playgroud)

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

>>> 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
Run Code Online (Sandbox Code Playgroud)

我们试图看看当前的序列是否可以是Truthy.这内部检查序列的长度是否为零(这只是一个简单的查找,因为列表的长度保存在变量中).如果长度为零,那么if not actions:将是Truthy.这里我们不构造一个新的列表,但我们只是隐式地检查长度,而不是明确地做

if len(actions) == 0:
Run Code Online (Sandbox Code Playgroud)

所以,我猜测Python Gurus的建议if not seq是因为它也有性能优势.

  • @renatov:我怀疑Guido,Tim和Barry比你更了解pythonic是什么,但是如果你不同意,可以试着说服Python社区需要改变PEP 8. (2认同)