Dlaczego "not (True) in [False, True]" zwraca False?

Jeśli to zrobię:

>>> False in [False, True]
True

To zwraca True. Po prostu dlatego, że False jest na liście.

Ale jeśli to zrobię:

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

To zwraca False. {[6] } jest równe False:

>>> not(True)
False
Dlaczego?
Author: Benjamin Hodgson, 2015-07-15

8 answers

Pierwszeństwo operatora 2.x, 3.x. Pierwszeństwo not jest mniejsze niż in. Jest więc równoważne:

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

Tego chcesz:

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

Jak zauważa @ Ben: zaleca się, aby nigdy nie pisać not(True), preferować not True. Pierwsza sprawia, że wygląda jak wywołanie funkcji, podczas gdy not jest operatorem, a nie funkcją.

 708
Author: Yu Hao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-22 01:13:46

not x in y jest oceniany jako x not in y

Możesz dokładnie zobaczyć, co się dzieje, demontując kod. Pierwszy przypadek działa zgodnie z oczekiwaniami:

>>> 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

Drugi przypadek, ocenia się na True not in [False, True], czyli False wyraźnie:

>>> 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        
>>> 

To, co chciałeś wyrazić zamiast (not(True)) in [False, True], które zgodnie z oczekiwaniami jest True, i możesz zobaczyć dlaczego:

>>> 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        
 72
Author: Roshan Mathews,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-15 04:39:48

Pierwszeństwo operatora. in wiąże się mocniej niż not, więc twoje wyrażenie jest równoważne not((True) in [False, True]).

 35
Author: mooiamaduck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-15 04:17:14

It ' s all about Operator precedence (in jest silniejszy niż not). Ale można to łatwo poprawić, dodając nawiasy we właściwym miejscu:

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

Zapis:

not(True) in [False, True]

Jest taki sam jak:

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

, który wygląda, jeśli True znajduje się na liście i zwraca "Nie" wyniku.

 33
Author: alfasin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-16 01:12:16

Jest oceniana jako not True in [False, True], która zwraca False, ponieważ True jest w [False, True]

Jeśli spróbujesz

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

Otrzymujesz oczekiwany wynik.

 14
Author: user3636636,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-15 04:18:32

Oprócz innych odpowiedzi, które wspominały o pierwszeństwie {[8] } jest niższe niż in, w rzeczywistości Twoje stwierdzenie jest równoważne:

not (True in [False, True])

Ale zauważ, że jeśli nie oddzielisz swojego warunku od innych, python użyje 2 ról (precedence lub chaining) w celu oddzielenia tego, i w tym przypadku python użył pierwszeństwa. Zauważ również, że jeśli chcesz oddzielić warunek, musisz umieścić wszystkie warunki w nawiasie, a nie tylko obiekt lub wartość :

(not True) in [False, True]

Ale jak już wspomniano, istnieje inna modyfikacja Pythona na operatorach, która jest łańcuchowanie :

Na podstawie Pythona dokumentacja :

Zauważ, że porównania, testy członkostwa i testy tożsamości mają ten sam priorytet i mają funkcję łańcucha od lewej do prawej , jak opisano w sekcji porównania.

Na przykład wynikiem następującego stwierdzenia jest False:

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

Ponieważ python będzie łańcuchem instrukcji w następujący sposób:

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

Czyli dokładnie False and True to jest False.

Można założyć, że centralny obiekt będzie współdzielony pomiędzy 2 operacjami i innymi obiektami (w tym przypadku False).

I zauważ, że jest to również prawdziwe dla wszystkich porównań, w tym testów członkostwa i operacji testów tożsamości, które są następujące operandy :

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

Przykład:

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

Kolejny słynny przykład is zakres liczb:

7<x<20

Która jest równa:

7<x and x<20   
 13
Author: Kasrâmvd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-01 14:43:09

Przyjrzyjmy się temu jako operacji sprawdzania przechowalni kolekcji: {[0] } jest listą zawierającą pewne elementy.

Wyrażenie True in [False, True] zwraca True, ponieważ True jest elementem zawartym w liście.

Dlatego not True in [False, True] daje "boolean opposite", not wynik powyższego wyrażenia (bez nawiasów, aby zachować pierwszeństwo, ponieważ in ma większy pierwszeństwo niż operator not). Dlatego not True spowoduje False.

Z drugiej strony, (not True) in [False, True], jest równa False in [False, True], czyli True (False znajduje się w wykazie).

 6
Author: Nick Louloudakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-15 19:05:01

Aby wyjaśnić niektóre z pozostałych odpowiedzi, dodanie nawiasów po operator jednoargumentowy nie zmienia swojego pierwszeństwa. not(True) nie wiąże not mocniej z True. To tylko zbędny zestaw nawiasów wokół True. To tak samo jak (True) in [True, False]. Nawiasy nic nie robią. Jeśli chcesz, aby Wiązanie było bardziej ciasne, musisz umieścić nawiasy wokół całego wyrażenia, co oznacza zarówno operator, jak i operand, tj. (not True) in [True, False].

Aby zobaczyć to innym sposobem, rozważ

>>> -2**2
-4

** wiąże się mocniej niż -, dlatego otrzymujemy ujemne dwa do kwadratu, a nie kwadrat ujemnych dwóch (które byłyby dodatnie cztery).

A gdybyś chciał kwadrat negatywnej dwójki? Oczywiście dodałbyś nawiasy:

>>> (-2)**2
4

Jednak nie jest rozsądne oczekiwać, że następujące dane dadzą 4

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

Ponieważ -(2) jest tym samym co -2. Nawiasy nie robią absolutnie nic. not(True) jest dokładnie to samo.

 6
Author: asmeurer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-19 00:12:43