Подтвердить что ты не робот

Неправильно ли использовать оператор "==" по сравнению с пустым списком?

PyCharm (4.0.6) жалуется, когда я делаю сравнение с пустым списком с помощью оператора ==, но это не происходит, когда я использую оператор is:

enter image description here

Я думаю, что это связано с PEP 8, но проблема в том, что, когда я использую оператор is, как предлагает PyCharm, у меня есть ложный отрицательный результат. Вот простой пример в оболочке iPython, чтобы показать, что в этом случае оператор == представляется более подходящим, так как оператор is возвращает ложный отрицательный результат:

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

Может кто-нибудь объяснить, почему PyCharm жалуется на оператора == по сравнению с пустым списком? Я делаю что-то неправильно в соответствии с PEP 8?

4b9b3361

Ответ 1

Цитата Раздел рекомендаций по программированию PEP-8,

Для последовательностей (строки, списки, кортежи) используйте тот факт, что пустые последовательности являются ложными.

Yes: if not seq:
     if seq:

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

Так как пустые последовательности являются Falsy в Python,

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

вы можете просто использовать if not, как указано в PEP-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

мы строим новый список, и это будет очень дорогостоящая операция, просто для сравнения. С другой стороны,

>>> 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: будет Truthy. Здесь мы не строим новый список, но мы просто проверяем длину неявно, вместо того, чтобы явно делать

if len(actions) == 0:

Итак, я предполагаю, что гуру Python предлагают if not seq, потому что также может быть преимущество в производительности.

Ответ 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)