python - ¿Por qué la asignación a True/False no funciona como espero?
python-2.x (5)
Como parte de responder a otra pregunta, escribí el siguiente código cuyo comportamiento parece extraño a primera vista:
print True # outputs true
True = False; print True # outputs false
True = True; print True # outputs false
True = not True; print True # outputs true
¿Alguien puede explicar este extraño comportamiento? Creo que tiene algo que ver con el modelo de objetos de Python, pero no estoy seguro.
Es la versión 2.5.2 de Cygwin.
En 2.x, True y False no son palabras clave, por lo que es posible seguir de cerca los elementos integrados.
Imagina esto en su lugar:
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
Exactamente lo mismo está sucediendo, pero en su versión es confuso, porque no espera que pueda redefinir True and False.
Puede restaurar fácilmente los valores originales usando comparaciones booleanas simples:
True = 1==1
False = 1==0
O al convertir literales enteros en bools:
True = bool(1) # actually every number except 0 works
False = bool(0)
Puede verificar si True / False es una palabra clave:
>>> import keyword
>>> keyword.iskeyword(''True'')
False
Como no es (en mi versión), asignar True = False solo significa "Verdadero" es otro nombre de "variable".
Python tiene estos dos (entre otros) objetos incorporados. Son solo objetos; al principio, todavía no tienen ningún nombre, pero para saber a qué nos referimos, llamémoslos 0x600D
y 0xBAD
.
Antes de comenzar a ejecutar un script de Python (2.x), el nombre True
se vincula al objeto 0x600D
, y el nombre False
se vincula al objeto 0xBAD
, por lo que cuando el programa se refiere a True
, se ve en 0x600D
.
Debido a que 0x600D
y 0xBAD
saben que generalmente se usan con los nombres True
y False
, eso es lo que producen cuando se imprimen, es decir, el método __str__
de 0x600D
devuelve ''True''
y así sucesivamente.
True = False
ahora vincula el nombre True
a un objeto diferente. A partir de ahora, los dos nombres True
y False
refieren al mismo objeto 0xBAD
, que, cuando se imprime, genera False
.
True = True
realmente no hace nada: toma el objeto al que se hace referencia con el nombre True
y vincula el nuevo (y antiguo) nombre True
a este objeto. Dado que (debido al paso anterior) True
refiere a 0xBAD
antes de esto, todavía se refiere a 0xBAD
después de esto. Por lo tanto, la impresión sigue emitiendo False
.
True = not True
primero toma el objeto al que está vinculado el nombre True
, que es 0xBAD
. Da este objeto al operador not
. not
importa (ni sabe) qué nombre se usa aquí para referirse a 0xBAD
, simplemente sabe que cuando se le da 0xBAD
debe devolver 0x600D
. Este valor de retorno se otorga al operador de asignación =
, vinculando el nombre True
a este objeto.
Dado que el nombre True
ahora una vez más se refiere al objeto 0x600D
, la llamada print True
0x600D
True
y el mundo vuelve a ser bueno.