«Х не в у» или «не х в у»

97

При тестировании на членство мы можем использовать:

x not in y

Или альтернативно:

not x in y

Для этого выражения может быть много возможных контекстов в зависимости от xи y. Это может быть, например, проверка подстроки, членство в списке, наличие ключа dict.

  • Всегда ли две формы эквивалентны?
  • Есть ли предпочтительный синтаксис?
вим
источник

Ответы:

112

Они всегда дают одинаковый результат.

Фактически, not 'ham' in 'spam and eggs'кажется, что он предназначен для выполнения одной операции "не в", а не для операции "в" и затем отрицания результата:

>>> import dis

>>> def notin():
    'ham' not in 'spam and eggs'
>>> dis.dis(notin)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE    

>>> def not_in():
    not 'ham' in 'spam and eggs'
>>> dis.dis(not_in)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE    

>>> def not__in():
    not ('ham' in 'spam and eggs')
>>> dis.dis(not__in)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        

>>> def noteq():
    not 'ham' == 'spam and eggs'
>>> dis.dis(noteq)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               2 (==)
              9 UNARY_NOT           
             10 POP_TOP             
             11 LOAD_CONST               0 (None)
             14 RETURN_VALUE      

Сначала я думал, что они всегда дают один и тот же результат, но сам notпо себе это был просто оператор логического отрицания с низким приоритетом, который можно было применить a in bтак же легко, как и любое другое логическое выражение, тогда как это not inбыл отдельный оператор для удобства и ясности .

Приведенная выше разборка показала! Кажется, что, хотя notочевидно, что это оператор логического отрицания, форма not a in bимеет специальный корпус, поэтому на самом деле он не использует общий оператор. Это делает not a in bбуквально то же самое выражение a not in b, а не просто выражение, которое приводит к тому же значению.

Бен
источник
4
Имейте в виду, что это всего лишь деталь реализации. Я даже не могу найти упоминания not x in xsв документации.
phant0m
1
@ phant0m Совершенно верно; как вы должны думать о not x in xsIS not (x in xs). Но тот факт, что он реализован путем анализа его в один и тот же байт-код, x not in xsочень ясно показывает, что они всегда должны быть идентичными, в отличие от таких вещей, как not x == yvs, x != yкоторые должны давать тот же результат, но не должны (в зависимости от реализаций __eq__и __ne__участвует).
Бен
11
Вы столкнулись с оптимизацией глазка CPython ; оптимизация времени компиляции, которую другие реализации Python, такие как Jython и IronPython, могут игнорировать или копировать (это не является частью спецификации языка).
Мартейн Питерс
15

  1. Нет, разницы нет.

    Оператор not inимеет обратное истинное значение in.

    - Документация Python

  2. Я бы предположил, not inчто это предпочтительнее, потому что это более очевидно, и они добавили для этого специальный случай.

icktoofay
источник
3

Другие уже очень ясно дали понять, что эти два утверждения, вплоть до довольно низкого уровня, эквивалентны.

Однако я не думаю, что кто-то еще достаточно подчеркнул, что, поскольку это оставляет выбор за вами, вы должны

выберите форму, которая делает ваш код максимально читаемым.

И не обязательно быть максимально читаемым для всех , даже если это, конечно, хорошая вещь, к которой нужно стремиться. Нет, убедитесь, что код максимально удобочитаем для вас , поскольку именно вы, скорее всего, вернетесь к этому коду позже и попытаетесь его прочитать.

Томас Ашан
источник
Если вы работаете в большой команде или над кодом, который, скорее всего, какое-то время останется нетронутым, более вероятно, что его придется поддерживать кому-то другому.
Томми Герберт
2

В Python разницы нет. И нет никаких предпочтений.

Игнасио Васкес-Абрамс
источник
1

Синтаксически это одно и то же утверждение. Я бы поспешил заявить, что это 'ham' not in 'spam and eggs'передает более ясное намерение, но я видел код и сценарии, в которых not 'ham' in 'spam and eggs'передается более ясное значение, чем у других.

Макото
источник