2010-01-13 9 views
31

Come parte di rispondere a un'altra domanda, ho scritto il seguente codice il cui comportamento sembra strano a prima vista:Perché l'assegnazione a True/False non funziona come previsto?

print True     # outputs true 
True = False; print True # outputs false 
True = True;  print True # outputs false 
True = not True; print True # outputs true 

Qualcuno può spiegare questo strano comportamento? Penso che abbia qualcosa a che fare con il modello a oggetti di Python ma non ne sono sicuro.

È la versione 2.5.2 di Cygwin.

+18

non è che una buona battuta vecchio '#define vero false' in azione qui? – Amarghosh

+2

Nella versione 3 l'asserzione True = False solleva un errore di sintassi, quindi suppongo che la tua domanda si riferisca alla versione 2 – jab

+2

che cosa c'è di strano in questo? cura di elaborare? – ghostdog74

risposta

73

Python ha questi due (e altri) oggetti incorporati. Sono solo oggetti; all'inizio, non hanno ancora alcun nome, ma per sapere a cosa ci riferiamo, chiamiamoli 0x600D e 0xBAD.

Prima di iniziare ad eseguire uno script Python (2.x), il nome True viene legato all'oggetto 0x600D, e il nome False viene legato all'oggetto 0xBAD, in modo che quando il programma si riferisce a True, esamina 0x600D .

Perché 0x600D e 0xBAD sanno che di solito vengono utilizzati con i nomi True e False, questo è quello che in uscita quando vengono stampate, vale a dire il metodo di 0x600D rendimenti 'True' e così via __str__.

True = False 

ora si lega il nome True a un oggetto diverso. D'ora in poi, entrambi i nomi True e False si riferiscono allo stesso oggetto 0xBAD, che, una volta stampato, emette False.

True = True 

in realtà non fa nulla: Ci vuole l'oggetto a cui si riferisce il nome True, e si lega il nuovo (e vecchio) nome True a questo oggetto. Poiché (a causa del passaggio precedente) True fa riferimento a 0xBAD prima, si riferisce ancora a 0xBAD dopo questo. Quindi, stampa ancora uscite False.

True = not True 

prima prende l'oggetto che il nome True è destinato a, che è 0xBAD. Dà questo oggetto all'operatore not. not non importa (o sapere) quale nome è usato qui per fare riferimento a 0xBAD, ma sa solo che quando viene dato 0xBAD deve restituire 0x600D.Questo valore di ritorno viene quindi assegnato all'operatore di assegnazione =, vincolando il nome True a questo oggetto.

Poiché il nome True ora ancora una volta fa riferimento all'oggetto 0x600D, chiamando print True uscite True, e il mondo è di nuovo bene.

+16

@paxdiablo: Di cosa stai parlando, "mnemonici"? Quelli sono gli indirizzi di memoria in cui ogni buona implementazione Python dovrebbe contenere questi oggetti :-P – balpha

+0

@ user127555 Lo so; "assignment is not an expression" è una delle mie funzionalità preferite di Python. Ma per quanto riguarda "nessun operatore di assegnazione": anche i [documenti ufficiali] (https://docs.python.org/2/reference/simple_stmts.html) fanno riferimento ad esso con quel nome. – balpha

17

In 2.x, True e False non sono parole chiave, quindi è possibile ombreggiare i built-in in questo modo.

41

Immaginate questo, invece:

A = True 
B = False 

print A   # true 
A = B; print A # false 
A = A; print A # false, because A is still false from before 
A = not A; print A # true, because A was false, so not A is true 

La stessa cosa sta succedendo, ma nella versione E 'confuso, perché non ci si aspetta che si può ridefinire Vero e Falso.

11

È possibile controllare se Vero/Falso è una parola chiave:

>>> import keyword 
>>> keyword.iskeyword('True') 
False 

Dal momento che non è (nella mia versione), assegnando Vero = False significa semplicemente "True" è un altro nome "variabile".

+1

Solo una nota che probabilmente dovresti usare 'keyword.iskeyword ('True')' come esempio, poiché la maggior parte delle parole chiave effettive fornisce un SyntaxError se utilizzato lì. –

+0

@Ig, sure.thanks – ghostdog74

+2

Nota: questo è corretto in python 3, True è una [parola chiave] (https://docs.python.org/3/reference/lexical_analysis.html#keywords). –

0

Si potrebbe facilmente ripristinare i valori originali utilizzando semplici confronti booleane:

True = 1==1 
False = 1==0 

o convertendo letterali interi a Caccio:

True = bool(1) # actually every number except 0 works 
False = bool(0) 
Problemi correlati