Почему «не (True) в [False, True]» возвращает False?

468

Если я это сделаю:

>>> False in [False, True]
True

Возвращает True. Просто потому, что False находится в списке.

Но если я это сделаю:

>>> not(True) in [False, True]
False

Возвращает False. Если not(True) равно False:

>>> not(True)
False

Почему?

  • 1
    связанные с stackoverflow.com/questions/31354429/…
  • 1
    Ваши круглые скобки сбивают с толку в not(True) in [False, True]
Теги:
python-3.x
python-2.7

8 ответов

725
Лучший ответ

Приоритет оператора 2.x, 3.x. Приоритет not ниже, чем у in. Таким образом, это эквивалентно:

>>> not (True in [False, True])
False

Это то, что вы хотите:

>>> (not True) in [False, True]
True

Как указывает @Ben: рекомендуется никогда не писать not(True), предпочитайте not True. Первый делает его похожим на вызов функции, а not является оператором, а не функцией.

  • 277
    @Texom512: Texom512: я бы также рекомендовал никогда не писать not(True) ; предпочитаю not True . Первый делает его похожим на вызов функции, откуда и возникла ваша путаница; если бы not было функцией, то not(True) in ... не могло бы быть not ((True) in ...) . Вы должны знать, что это оператор (или вы попадаете в подобные ситуации), поэтому вы должны писать его как оператор, а не маскировать его как функцию.
  • 7
    Кроме того, если вы собираетесь использовать интервалы, чтобы указать приоритет для читателя, сначала убедитесь, что вы правы. Вероятно, нормально писать a + b*c + d , очень плохо писать a+b * c+d . Так что not(True) тоже плохо по этой мере.
Показать ещё 5 комментариев
70

not x in y оценивается как x not in y

Вы можете точно видеть, что происходит при разборке кода. Первый случай работает так, как вы ожидаете:

>>> x = lambda: False in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (False)
              3 LOAD_GLOBAL              0 (False)
              6 LOAD_GLOBAL              1 (True)
              9 BUILD_LIST               2
             12 COMPARE_OP               6 (in)
             15 RETURN_VALUE

Второй случай оценивается True not in [False, True], который False четко:

>>> x = lambda: not(True) in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_GLOBAL              1 (False)
              6 LOAD_GLOBAL              0 (True)
              9 BUILD_LIST               2
             12 COMPARE_OP               7 (not in)
             15 RETURN_VALUE        
>>> 

Вместо этого вы хотели бы выразить (not(True)) in [False, True], который, как и ожидалось, True, и вы можете понять, почему:

>>> x = lambda: (not(True)) in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (True)
              3 UNARY_NOT           
              4 LOAD_GLOBAL              1 (False)
              7 LOAD_GLOBAL              0 (True)
             10 BUILD_LIST               2
             13 COMPARE_OP               6 (in)
             16 RETURN_VALUE        
  • 13
    Всегда есть парень с dis но это очень ценный ответ, потому что он показывает, что на самом деле not in используется
  • 21
    Байт-код - это деталь реализации интерпретатора CPython. Это ответ CPython на вопрос о Python, на самом деле на него лучше ответить непосредственно из языковой справки.
Показать ещё 1 комментарий
35

Приоритет оператора. in связывается сильнее, чем not, поэтому ваше выражение эквивалентно not((True) in [False, True]).

35

Все о приоритет оператора (in сильнее, чем not). Но его можно легко скорректировать, добавив круглые скобки в нужное место:

(not(True)) in [False, True]  # prints true

записывания:

not(True) in [False, True]

то же самое:

not((True) in [False, True])

который выглядит, если True находится в списке и возвращает "нет" результата.

14

Он оценивается как not True in [False, True], который возвращает False, потому что True находится в [False, True]

Если вы попробуете

>>>(not(True)) in [False, True]
True

Вы получите ожидаемый результат.

13

Наряду с другими ответами, в которых упоминалось, что приоритет not ниже in, на самом деле ваше утверждение эквивалентно:

not (True in [False, True])

Но обратите внимание, что если вы не отделите свое условие от других, python будет использовать 2 роли (precedence или chaining), чтобы отделить их, и в этом случае приоритет python. Кроме того, обратите внимание, что если вы хотите отделить условие, вам нужно поставить все условие в скобки, а не только объект или значение:

(not True) in [False, True]

Но, как уже упоминалось, существует еще одна модификация python для операторов, которая цепочка:

На основе python документация:

Обратите внимание, что сравнения, тесты членства и тесты идентичности имеют одинаковый приоритет и имеют функцию привязки слева направо цепочка, как описано в разделе "Сравнение".

Например, результат следующей инструкции: False:

>>> True == False in [False, True]
False

Поскольку python будет связывать операторы следующим образом:

(True == False) and (False in [False, True])

Что именно False and True, которое False.

Можно предположить, что центральный объект будет разделен между двумя операциями и другими объектами (в этом случае False).

Обратите внимание, что это также верно для всех сравнений, включая тесты на членство и операции проверки идентичности, следующие операнды:

in, not in, is, is not, <, <=, >, >=, !=, ==

Пример:

>>> 1 in [1,2] == True
False

Другим известным примером является диапазон номеров:

7<x<20

который равен:

7<x and x<20   
6

Чтобы уточнить некоторые другие ответы, добавление круглых скобок после унарного оператора не изменяет его приоритет. not(True) не делает привязку not более жесткой к True. Это просто избыточный набор круглых скобок вокруг True. Он почти такой же, как (True) in [True, False]. Скобки не делают ничего. Если вы хотите, чтобы привязка была более жесткой, вы должны поместить круглые скобки вокруг всего выражения, что означает как оператор, так и операнд, т.е. (not True) in [True, False].

Чтобы увидеть этот другой способ, рассмотрим

>>> -2**2
-4

** связывается сильнее, чем -, поэтому вы получаете отрицательный результат от двух квадратов, а не от квадрата отрицательных двух (что было бы положительно четыре).

Что, если вы хотите квадрат отрицательных двух? Очевидно, вы добавили бы круглые скобки:

>>> (-2)**2
4

Однако не разумно ожидать, что следующее даст 4

>>> -(2)**2
-4

потому что -(2) совпадает с -2. Скобки не имеют абсолютно ничего. not(True) - это точно то же самое.

6

Посмотрите на него как на проверку проверки сдерживания коллекции: [False, True] - это список, содержащий некоторые элементы.

Выражение True in [False, True] возвращает True, поскольку True - это элемент, содержащийся в списке.

Следовательно, not True in [False, True] дает результат "boolean contrast", not из приведенного выше выражения (без каких-либо круглых скобок для сохранения приоритета, поскольку in имеет больший приоритет, чем оператор not). Следовательно, not True приведет к False.

С другой стороны, (not True) in [False, True], равно False in [False, True], который True (False содержится в списке).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню