False == 0 e True == 1 sono dettagli di implementazione o sono garantiti dalla lingua?


245

È garantito che False == 0e True == 1, in Python (supponendo che non siano riassegnati dall'utente)? Ad esempio, è in qualche modo garantito che il seguente codice produrrà sempre gli stessi risultati, qualunque sia la versione di Python (sia quella esistente che, probabilmente, futura)?

0 == False  # True
1 == True   # True
['zero', 'one'][False]  # is 'zero'

Qualsiasi riferimento alla documentazione ufficiale sarebbe molto apprezzato!

Modifica : come indicato in molte risposte, booleredita da int. La domanda può quindi essere riformulata come: "La documentazione dice ufficialmente che i programmatori possono fare affidamento su valori01 booleani ereditati da numeri interi, con i valori e ?". Questa domanda è rilevante per la scrittura di codice robusto che non fallirà a causa dei dettagli di implementazione!


63
@ S.Lott: ci sono molti motivi per porre la domanda sopra. Quindi, ci sono casi in cui fare affidamento sul fatto che i valori booleani siano numeri interi rende il codice più semplice: devi cambiarlo? Oppure, potresti individuare dei punti in un codice scritto da qualcun altro che si basa sul fatto che i valori booleani sono numeri interi: interrompi ciò che stai modificando nel codice per "riparare" il codice esistente o puoi essere certo che la codifica corrente è valida ? C'è una miriade di altri esempi. Più in generale, è bene conoscere le regole del gioco, in modo da poter giocare bene e programmare in modo corretto.
Eric O Lebigot,

10
@ S.Lott: il post originale riprende esattamente il tuo punto: la domanda è essenzialmente "È un dettaglio di implementazione?", Perché concordo pienamente con te sull'idea che non si dovrebbe dipendere dai dettagli di implementazione. Se i booleani sono ufficialmente numeri interi di valori noti, il codice nella domanda non si basa sui dettagli di implementazione, il che è positivo.
Eric O Lebigot,

5
@S. Lotto: Sapendo che False == 0 e True == 1 semplifica il conteggio del numero di bool in una sequenza: puoi semplicemente scrivere sum(bool_list). Altrimenti, dovresti scrivere sum(1 for x bool_list if x).
dan04,

8
@dan: è un modo per contare i booleani. Direi che bool_list.count(True)è più esplicito; è anche circa 3 volte più veloce ... :)
Eric O Lebigot il

2
@akonsu Come mostrano le risposte, i booleani di Python sono in realtà (una sottoclasse specifica di) numeri interi. Inoltre, Python ha ovviamente dei tipi; forse volevi dire che non è "tipizzato staticamente"? Inoltre, non sono sicuro di cosa intendi con "Non farei errori nel codice". Ora, non mi piace mai mescolare i booleani con i numeri interi, perché concettualmente diversi, e non mi dispiacerebbe se i booleani di Python non fossero numeri interi, ma è utile sapere che lo sono, con i valori 0 e 1.
Eric O Lebigot,

Risposte:


184

In Python 2.x questo non è garantito in quanto è possibile Truee Falseda riassegnare. Tuttavia, anche se ciò accade, i valori booleani True e booleani False vengono comunque restituiti correttamente per i confronti.

In Python 3.x Truee Falsesono le parole chiave e sarà sempre uguale a 1e 0.

In circostanze normali in Python 2 e sempre in Python 3:

Falsel'oggetto è di tipo boolche è una sottoclasse di int:

object
   |
 int
   |
 bool

È l'unica ragione per cui nel tuo esempio ['zero', 'one'][False]funziona. Non funzionerebbe con un oggetto che non sia una sottoclasse di numeri interi, poiché l'indicizzazione dell'elenco funziona solo con numeri interi o oggetti che definiscono un __index__metodo (grazie a mark-dickinson ).

Modificare:

È vero per l'attuale versione di Python e per quella di Python 3. I documenti per Python 2.6 e i documenti per Python 3 dicono entrambi:

Esistono due tipi di numeri interi: [...] Integer (int) [...] Booleans (bool)

e nella sottosezione booleana:

Booleani: rappresentano i valori di verità Falso e Vero [...] I valori booleani si comportano come i valori 0 e 1, rispettivamente, in quasi tutti i contesti, con l'eccezione che quando vengono convertiti in una stringa, le stringhe "Falso" o "Vero "vengono restituiti, rispettivamente.

C'è anche, per Python 2 :

In contesti numerici (ad esempio se usati come argomento per un operatore aritmetico), [Falso e Vero] si comportano come gli interi 0 e 1, rispettivamente.

Quindi i booleani sono esplicitamente considerati come numeri interi in Python 2.6 e 3.

Quindi sei al sicuro fino all'arrivo di Python 4. ;-)


2
0 == 0.0 restituisce True mentre ['zero', 'one'] [0.0] fallisce. ['zero', 'one'] [False] funziona perché bool è una sottoclasse di int. (int .__ sottoclassi __ () restituisce [<type 'bool'>])
luc

20
Nitpick: qualsiasi oggetto che fornisce un __index__metodo può essere utilizzato come indice di elenco; non solo sottoclassi di into long.
Mark Dickinson,

Ah sì, è anche lì. Ma sarebbe meglio non collegarsi alla documentazione di Python 3.0: 3.0 è morto. :)
Mark Dickinson,

4
Ri: "In Python 2.x questo non è garantito in quanto è possibile riassegnare True e False". IMHO, mentre questo è vero, chiunque riassegni True o False merita qualunque strana conseguenza ottengano. In particolare, l'archiviazione di True prima della riassegnazione e quindi il confronto del risultato con True dopo la riassegnazione verrebbero interrotti. a = True; True = 'i am an idiot'; a == True=> Falso. A parte tale riassegnazione, i valori predefiniti sono standardizzati come 0 e 1, e credo che sia pratica comune dipendere da quello; ad es. per indicizzare in una matrice a due elementi, dove [0] contiene il caso falso, [1] vero.
ToolmakerSteve

Ho appena notato un'altra conferma ufficiale del fatto che True può in pratica essere considerato come 1 e False 0: docs.python.org/2/library/stdtypes.html#boolean-values . Sto aggiungendo questo a questa risposta.
Eric O Lebigot,

78

Link al PEP che discute il nuovo tipo di bool in Python 2.3: http://www.python.org/dev/peps/pep-0285/ .

Quando si converte un bool in un int, il valore intero è sempre 0 o 1, ma quando si converte un bo in un valore booleano, il valore booleano è True per tutti i numeri interi tranne 0.

>>> int(False)
0
>>> int(True)
1
>>> bool(5)
True
>>> bool(-5)
True
>>> bool(0)
False

22

In Python 2.x, non è affatto garantito:

>>> False = 5
>>> 0 == False
False

Quindi potrebbe cambiare. In Python 3.x, True, False e None sono parole riservate , quindi il codice sopra riportato non funzionerebbe.

In generale, con i booleani dovresti supporre che mentre False avrà sempre un valore intero pari a 0 (purché non lo modifichi, come sopra), True potrebbe avere qualsiasi altro valore. Non farei necessariamente affidamento su alcuna garanzia che True==1, ma su Python 3.x, sarà sempre così, qualunque cosa accada.


3
Ri "True potrebbe avere qualsiasi altro valore. Non farei necessariamente affidamento su alcuna garanzia che True == 1". In realtà, PUOI fare affidamento su True == 1, come da python.org/dev/peps/pep-0285 , e spec docs.python.org/2/reference/… "I valori booleani si comportano come i valori 0 e 1, rispettivamente , in quasi tutti i contesti ... "Non sto dicendo che è impossibile scavalcarlo in Py 2 riassegnando True o False, ma sto dicendo che a meno che qualche programmatore del tuo progetto non sia un idiota e faccia una tale riassegnazione, il il comportamento è garantito.
ToolmakerSteve

-2

Molto semplice. Poiché bool si riferisce alla valutazione di un numero intero come bool, SOLO zero fornisce una risposta falsa. TUTTI i valori diversi da zero, float, numeri interi, compresi i numeri negativi o ciò che hai, restituiranno true.

Un buon esempio del perché questo è utile è determinare lo stato di alimentazione di un dispositivo. On è qualsiasi valore diverso da zero, off è zero. Parlando elettronicamente questo ha senso.

Per determinare il vero o il falso relativamente tra i valori, è necessario disporre di qualcosa con cui confrontarlo. Questo vale per le stringhe e valori numerici, utilizzando ==o !=oppure <, > >=, <=, etc.

È possibile assegnare un numero intero a una variabile e quindi ottenere vero o falso in base a quel valore di variabile.


1
La domanda è se True == 1 è garantito da Python, non sul valore booleano degli interi.
Eric O Lebigot,

-3

Basta scrivere int(False)e otterrai 0, se digiti int(True), verrà generato1


4
Questo significa solo che False e True sono input validi per int(), con un semplice significato numerico, non che sono esattamente identici a 0 e 1.
Eric O Lebigot

-5

False è un bool. Ha un tipo diverso. È un oggetto diverso da 0 che è un numero intero.

0 == Falserestituisce True perché False viene trasmesso a un numero intero. int (False) restituisce 0

La documentazione di Python dell'operatore == dice (aiuto ('==')):

Gli operatori <, >, ==, >=, <=, e !=confronta i valori di due oggetti. Gli oggetti non devono avere lo stesso tipo. Se entrambi sono numeri, vengono convertiti in un tipo comune.

Di conseguenza False viene convertito in un numero intero per la necessità del confronto. Ma è diverso da 0.

>>> 0 is False
False

26
Questo non è del tutto giusto: boolè una sottoclasse di int, quindi in un senso molto reale un bool è un numero intero. Ad esempio, isinstance(True, int)restituisce True. E il controllo dell'uguaglianza non converte il bool in un int, poiché non è necessaria alcuna conversione: chiama semplicemente int.__cmp__direttamente. Si noti che bool.__cmp__ is int.__cmp__valuta anche True.
Mark Dickinson,

3
-1 per questa risposta. Descrizione errata della relazione tra bool e int (in Python 2). isinstance(True, int)=> Vero. Cioè, True È un numero intero e non richiede conversione.
ToolmakerSteve

Avevo una sceneggiatura che restituiva False o Int ... usando while response is Falsefunzionato, e while response == Falsenon .. Grazie!
curly_brackets il

5
Questo 0 is Falseè falso non ti dice nulla. Nell'interprete interattivo, inserisci x = -10, quindi y = -10, quindi x is ye anche quello sarà falso. Solo perché ci sono ottimizzazioni in atto in cui l'interprete Python riutilizza gli stessi oggetti interi in determinate circostanze (memorizzazione di valori letterali interi come costanti, internamento di numeri interi piccoli) non significa che isdovrebbe essere usato quando si desidera verificare l' uguaglianza del valore intero .
Martijn Pieters
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.