2015-07-15 21 views
449

Se faccio questo:Perché "non (Vero) in [Falso, Vero]" restituisce False?

>>> False in [False, True] 
True 

che restituisce True. Semplicemente perché False è nella lista.

Ma se faccio:

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

che restituisce False. Mentre not(True) è pari a False:

>>> not(True) 
False 

Perché?

+0

correlati http://stackoverflow.com/questions/31354429/why-is-true-is-false-false-false-in-python/31354514#31354514 – Kasramvd

risposta

697

Precedenza degli operatori2.x, 3.x. La precedenza di not è inferiore a quella di in. Così è equivalente a:

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

Questo è ciò che si vuole:

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

Come @ Ben sottolinea: Si consiglia di non scrivere mai not(True), preferiscono not True. Il primo lo fa sembrare una chiamata di funzione, mentre not è un operatore, non una funzione.

+267

@ Texom512: vorrei anche raccomandare di non scrivere mai 'no (true) '; preferisco "non vero". Il primo lo fa sembrare una chiamata di funzione, da cui proviene la tua confusione; se 'not' era una funzione, quindi' not (True) in ... 'non poteva essere' not ((True) in ...) '. Devi sapere che è un operatore (o finisci in situazioni come questa), quindi dovresti scriverlo come un operatore, non mascherarlo come una funzione. – Ben

+7

Inoltre, se si intende utilizzare la spaziatura per indicare la precedenza a beneficio del lettore, assicurarsi innanzitutto di avere ragione. Probabilmente è OK scrivere 'a + b * c + d', è molto brutto scrivere' a + b * c + d'. Quindi 'not (True)' è male anche per quella misura. –

+18

In realtà, ** mai ** scrivi 'non vero '. Scrivi 'False' invece. – Darkhogg

35

Precisione dell'operatore. in si lega più strettamente di not, quindi l'espressione è equivalente a not((True) in [False, True]).

33

Si tratta di operator precedence (in è più potente di not). Ma può essere facilmente corretto con l'aggiunta di parentesi al posto giusto:

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

scrittura:

not(True) in [False, True] 

è lo stesso come:

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

che guarda se True è nella lista e restituisce il "non" del risultato.

14

Si sta valutando come not True in [False, True], che restituisce False perché True è in [False, True]

Se si tenta

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

Si ottiene il risultato atteso.

71

not x in y viene valutata come x not in y

Si può vedere esattamente cosa sta succedendo attraverso la scomposizione del codice.Il primo caso funziona come previsto:

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

Il secondo caso, restituisce True not in [False, True], che è False chiaramente:

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

quello che si voleva esprimere invece era (not(True)) in [False, True], che come previsto è True, e puoi vedere perché:

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

C'è sempre un ragazzo con 'dis', ma questa è una risposta molto valida perché mostra che in realtà 'non in' è utilizzato – jamylak

+21

Bytecode è un dettaglio di implementazione dell'interprete CPython. Questa è una risposta di CPython a una domanda di Python, infatti è possibile ottenere una risposta migliore direttamente dal riferimento del linguaggio. – wim

+4

@wim direi che l'implementazione bytecode non è importante quanto lo smontaggio effettivo. Altre implementazioni sono garantite per generare qualcosa funzionalmente identico, quindi la comprensione di uno smontaggio offre informazioni sufficienti per comprendere il "perché" e non il "come" di livello inferiore. –

6

Vediamolo come un'operazione di controllo del contenimento delle raccolte: [False, True] è una lista contenente alcuni elementi.

L'espressione True in [False, True] restituisce True, come True è un elemento contenuto nell'elenco.

Pertanto, not True in [False, True] pronunciato la "opposto boolean", not risultato dell'espressione sopra (senza parentesi per preservare la precedenza, come in ha precedenza maggiore rispetto not operatore). Pertanto, not True corrisponderà a False.

D'altra parte, (not True) in [False, True], è pari a False in [False, True], che è True (False è contenuto nella lista).

13

Accanto alle altre risposte che parlano del precedenza di not è inferiore in, in realtà la sua dichiarazione è equivalente a:

not (True in [False, True]) 

ma è da notare che se non separare la sua condizione dalle altre, pitone userà 2 ruoli (precedence o chaining) per separarlo, e in questo caso python ha usato la precedenza. Si noti inoltre che se si vuole separare una condizione è necessario mettere tutte le condizioni tra parentesi non solo l'oggetto o il valore:

(not True) in [False, True] 

Ma, come accennato, v'è un'altra modifica da Python a operatori che è concatenamento:

sulla base di pitone documentation:

Nota che i confronti, i test di appartenenza, e test d'identità, un Avremo la stessa precedenza e avremo una funzionalità da sinistra a destra che concatena la funzione come descritto nella sezione Confronti.

Per esempio il risultato della seguente dichiarazione è False:

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

perché catena Python le dichiarazioni come segue:

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

Che è esattamente False and True che è False.

È possibile assumere che l'oggetto centrale verrà condiviso tra 2 operazioni e altri oggetti (False in questo caso).

E nota che il suo vero anche per tutti i confronti, inclusi i test di appartenenza e le operazioni di test d'identità che sono seguenti operandi:

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

Esempio:

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

Un altro esempio famoso è intervallo di numeri:

7<x<20 

che è uguale a:

7<x and x<20 
6

Per chiarire su alcune delle altre risposte, aggiungendo tra parentesi dopo un operatore unario non cambia la sua precedenza. not(True) non effettua il not vincolo più stretto a True. È solo un insieme ridondante di parentesi intorno allo True. È lo stesso di (True) in [True, False]. Le parentesi non fanno nulla. Se si desidera che la rilegatura sia più stretta, è necessario posizionare le parentesi intorno all'intera espressione, ovvero sia l'operatore che l'operando, ovvero (not True) in [True, False].

Per vedere in un altro modo, considerano

>>> -2**2 
-4 

** si lega più strettamente di -, motivo per cui si ottiene il negativo di due quadrati, non è la piazza di negativo due (il che sarebbe positivo quattro).

E se voleste il quadrato del negativo due? Ovviamente, si potrebbe aggiungere parentesi:

>>> (-2)**2 
4 

Tuttavia, non è ragionevole aspettarsi quanto segue per dare 4

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

perché -(2) è lo stesso di -2. Le parentesi non fanno assolutamente nulla. not(True) è esattamente lo stesso.

Problemi correlati