Чому “Не (Істинно) у [Неправдивому, Істинному]” повертається Невірно?


483

Якщо я це роблю:

>>> False in [False, True]
True

Це повертається True. Просто тому, що Falseє в списку.

Але якщо я:

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

Це повертається False. Тоді not(True)як дорівнює False:

>>> not(True)
False

Чому?



2
ваші дужки плутаються вnot(True) in [False, True]
Гріеш Чаухан

Відповіді:


730

Пріоритет операторів 2.x , 3.x . Пріоритет notнижчий, ніж у in. Отже, це рівнозначно:

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

Це те, що ви хочете:

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

Як @Ben вказує: рекомендується ніколи не писати not(True), віддайте перевагу not True. Перший робить це схожим на виклик функції, а notоператор, а не функцію.


279
@ Texom512: Я б також рекомендував ніколи не писати not(True); віддайте перевагу not True. Перший робить це схожим на виклик функції, звідки виникла ваша плутанина; якщо це notбула функція, то not(True) in ...не могло бути not ((True) in ...). Ви повинні знати, що це оператор (або ви потрапляєте в подібні ситуації), тому слід писати його як оператор, а не маскувати його як функцію.
Бен

7
Крім того, якщо ви збираєтесь використовувати інтервали для позначення переваги на користь читача, спочатку переконайтеся, що ви праві. Мабуть, добре писати a + b*c + d, дуже погано писати a+b * c+d. Так not(True)погано і за цим заходом.
Стів Джессоп

32
Власне, ніколи не пишіть not True. Напишіть Falseзамість цього.
Darkhogg

10
Імовірно, у реальному житті ви б не писали not True, ви писали б щось на зразок not myfunc(x,y,z)де myfuncє якась функція, яка повертається Trueабо False.
Nate CK

3
@ BenC.R.Leggiero Ось що я зробив у оригінальній відповіді , а інші виправили це. Поточна версія для мене досить зрозуміла, я не думаю, що її важко зрозуміти без зайвих дужок, оскільки ключова проблема була вказана, розуміння решти - основна майстерність програміста.
Yu Hao

76

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використовується
jamylak

21
Байт-код - це деталь реалізації інтерпретатора CPython. Це відповідь CPython на питання Python, адже на нього можна краще відповісти безпосередньо з мовної посилання.
Вім

5
@wim Я заперечу, що реалізація байт-коду не так важлива, як власне розбирання. Інші реалізації гарантовано створюють щось функціонально ідентичне, тому розуміння однієї розбирання пропонує достатньо розуміння, щоб зрозуміти "чому", а не низький рівень "як".
Алекс Пана

36

Пріоритет оператора. inпов'язує більш щільно, ніж not, тому ваш вираз еквівалентний not((True) in [False, True]).


33

Вся справа в пріоритеті оператора ( 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.

Можна припустити, що центральний об’єкт буде розділений між двома операціями та іншими об'єктами (в цьому випадку помилковим).

І зауважте, що це справедливо і для всіх порівнянь, включаючи тести членства та операції тестування ідентичності, які є наступними операндами:

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

Приклад:

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

Ще один відомий приклад - діапазон чисел:

7<x<20

що дорівнює:

7<x and x<20   

6

Давайте розглянемо це як операцію перевірки [False, True]вмісту колекції: це список, що містить деякі елементи.

Вираз True in [False, True]повертається True, як Trueі елемент, що міститься у списку.

Отже, not True in [False, True]дає "булеву протилежність", notрезультат вищевказаного виразу (без жодних дужок для збереження пріоритету, оскільки inмає більший пріоритет, ніж notоператор). Тому not Trueрезультат False.

З іншого боку (not True) in [False, True],, дорівнює False in [False, True], що є True( Falseміститься в списку).


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)точно так само.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.