Pourquoi n'assignant à Vrai / Faux fonctionne pas comme je l'attends?
-
20-09-2019 - |
Question
Dans le cadre de répondre à une autre question, j'ai écrit le code suivant dont le comportement semble bizarre à première vue:
print True # outputs true
True = False; print True # outputs false
True = True; print True # outputs false
True = not True; print True # outputs true
Quelqu'un peut-il expliquer ce comportement étrange? Je pense qu'il a quelque chose à voir avec le modèle objet de Python, mais je ne suis pas sûr.
Il est la version 2.5.2 sous Cygwin.
La solution
Python a ces deux (entre autres) des objets builtin. Ils sont juste des objets; au début, ils n'ont pas encore de nom, mais de savoir ce que nous appelons, nous allons les appeler 0x600D
et 0xBAD
.
Avant de commencer à exécuter un script, le nom True
Python (2.x) obtient lié à la 0x600D
d'objet, et le nom False
obtient lié à la 0xBAD
d'objet, donc quand le programme se réfère à True
, il regarde 0x600D
.
Parce que 0x600D
et 0xBAD
savent qu'ils sont généralement utilisés par les noms True
et False
, c'est ce qu'ils sortie quand ils sont imprimés, à savoir la méthode __str__
de 0x600D
retourne 'True'
et ainsi de suite.
True = False
se fixe maintenant le nom True
à un autre objet. Désormais, les deux noms True
et False
se réfèrent au même objet 0xBAD
, qui, lors de l'impression, les sorties False
.
True = True
ne pas vraiment faire quelque chose: Il prend l'objet visé par le nom True
et lie le nouveau (et ancien) nom True
à cet objet. Depuis (en raison de l'étape précédente) True
fait référence à 0xBAD
avant cela, il fait toujours référence à 0xBAD
après. Par conséquent, l'impression émet toujours False
.
True = not True
prend d'abord l'objet que le nom True
est lié, qui est 0xBAD
. Il donne cet objet à l'opérateur not
. not
ne se soucie (ou savoir) quel nom est utilisé ici pour se référer à 0xBAD
, il sait juste que quand donné 0xBAD
il doit retourner 0x600D
. Cette valeur de retour est ensuite donnée à l'opérateur d'affectation =
, liant le nom True
à cet objet.
Depuis le nom True
maintenant une fois de plus fait référence à l'objet 0x600D
, appelant sorties print True
True
, et le monde est bon à nouveau.
Autres conseils
Imaginez ceci:
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 même chose se passe, mais dans votre version, il est source de confusion, parce que vous ne vous attendez pas que vous pouvez redéfinir Vrai et Faux.
Dans 2.x, Vrai et faux ne sont pas des mots-clés il est donc possible d'ombre les Encastrements de cette manière.
Vous pouvez vérifier si Vrai / Faux est un mot clé:
>>> import keyword
>>> keyword.iskeyword('True')
False
Comme ce n'est pas (dans ma version), attribuer Vrai = Faux signifie simplement que le nom "True" est une autre "variable".
Vous pouvez facilement restaurer les valeurs d'origine à l'aide de simples comparaisons booléennes:
True = 1==1
False = 1==0
Ou en convertissant les littéraux entiers à bools:
True = bool(1) # actually every number except 0 works
False = bool(0)