Если я это сделаю:
>>> False in [False, True]
True
Возвращает True
. Просто потому, что False
находится в списке.
Но если я это сделаю:
>>> not(True) in [False, True]
False
Возвращает False
. Если not(True)
равно False
:
>>> not(True)
False
Почему?
Приоритет оператора 2.x, 3.x. Приоритет not
ниже, чем у in
. Таким образом, это эквивалентно:
>>> not (True in [False, True])
False
Это то, что вы хотите:
>>> (not True) in [False, True]
True
Как указывает @Ben: рекомендуется никогда не писать not(True)
, предпочитайте not True
. Первый делает его похожим на вызов функции, а not
является оператором, а не функцией.
not(True)
; предпочитаю not True
. Первый делает его похожим на вызов функции, откуда и возникла ваша путаница; если бы not
было функцией, то not(True) in ...
не могло бы быть not ((True) in ...)
. Вы должны знать, что это оператор (или вы попадаете в подобные ситуации), поэтому вы должны писать его как оператор, а не маскировать его как функцию.
a + b*c + d
, очень плохо писать a+b * c+d
. Так что not(True)
тоже плохо по этой мере.
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
dis
но это очень ценный ответ, потому что он показывает, что на самом деле not in
используется
Приоритет оператора. in
связывается сильнее, чем not
, поэтому ваше выражение эквивалентно not((True) in [False, True])
.
Все о приоритет оператора (in
сильнее, чем not
). Но его можно легко скорректировать, добавив круглые скобки в нужное место:
(not(True)) in [False, True] # prints true
записывания:
not(True) in [False, True]
то же самое:
not((True) in [False, True])
который выглядит, если True
находится в списке и возвращает "нет" результата.
Он оценивается как not True in [False, True]
, который возвращает False
, потому что True
находится в [False, True]
Если вы попробуете
>>>(not(True)) in [False, True]
True
Вы получите ожидаемый результат.
Наряду с другими ответами, в которых упоминалось, что приоритет 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
Чтобы уточнить некоторые другие ответы, добавление круглых скобок после унарного оператора не изменяет его приоритет. 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)
- это точно то же самое.
Посмотрите на него как на проверку проверки сдерживания коллекции: [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
содержится в списке).
not(True) in [False, True]