Al investigar Queue.py en Python 2.6, encontré esta construcción que me pareció un poco extraña:
def full(self):
"""Return True if the queue is full, False otherwise
(not reliable!)."""
self.mutex.acquire()
n = 0 < self.maxsize == self._qsize()
self.mutex.release()
return n
Si maxsize
es 0, la cola nunca está llena.
Mi pregunta es ¿cómo funciona para este caso? ¿Cómo 0 < 0 == 0
se considera falso?
>>> 0 < 0 == 0
False
>>> (0) < (0 == 0)
True
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
>>> (0) < (0 == 0)
, claramente no lo es.n = 0 < self.maxsize == self._qsize()
en primer lugar, en ningún idioma. Si sus ojos tienen que moverse de un lado a otro de la línea varias veces para descubrir lo que está sucediendo, no es una línea bien escrita. Simplemente divídalo en varias líneas.Respuestas:
Creo que Python tiene un manejo de casos especial para secuencias de operadores relacionales para hacer que las comparaciones de rango sean fáciles de expresar. Es mucho más agradable poder decir
0 < x <= 5
que decir(0 < x) and (x <= 5)
.Estas se llaman comparaciones encadenadas . Y ese es un enlace a la documentación para ellos.
Con los otros casos de los que habla, los paréntesis obligan a un operador relacional a aplicarse antes que al otro, por lo que ya no son comparaciones encadenadas. Y dado que
True
yFalse
tiene valores como enteros, obtiene las respuestas que hace de las versiones entre paréntesis.fuente
Porque
es
False
. Puede encadenar operadores de comparación y se expanden automáticamente en las comparaciones por pares.EDITAR: aclaración sobre verdadero y falso en Python
En Python
True
yFalse
son solo instancias debool
, que es una subclase deint
. En otras palabras,True
realmente es solo 1.El punto de esto es que puede usar el resultado de una comparación booleana exactamente como un entero. Esto lleva a cosas confusas como
Pero esto solo sucederá si entre paréntesis las comparaciones para que se evalúen primero. De lo contrario, Python expandirá los operadores de comparación.
fuente
'success' if result_code == 0 else 'failure'
puede reescribirse ya que('error', 'success')[result_code == 0]
, antes de esto, nunca había visto un booleano utilizado para seleccionar un elemento en una lista / tupla.El comportamiento extraño que experimentas proviene de la habilidad de las pitones para encadenar las condiciones. Como encuentra que 0 no es menor que 0, decide que toda la expresión se evalúa como falsa. Tan pronto como separe esto en condiciones separadas, cambiará la funcionalidad. Inicialmente está probando esencialmente eso
a < b && b == c
para su declaración original dea < b == c
.Otro ejemplo:
fuente
a < b && b == c
es lo mismo quea < b == c
OOEsta es una comparación encadenada. Devuelve verdadero si cada comparación por pares a su vez es verdadera. Es el equivalente a
(0 < 0) and (0 == 0)
Esto es equivalente a lo
0 < True
que se evalúa como Verdadero.Esto es equivalente a lo
False == 0
que se evalúa como Verdadero.Equivalente a lo
0 < True
que, como anteriormente, se evalúa como Verdadero.fuente
Mirando el desmontaje (los códigos de bytes) es obvio por qué
0 < 0 == 0
esFalse
.Aquí hay un análisis de esta expresión:
Observe las líneas 0-8: estas líneas verifican si
0 < 0
obviamente regresaFalse
a la pila de Python.Ahora observe la línea 11:
JUMP_IF_FALSE_OR_POP 23
Esto significa que si0 < 0
regresa,False
realice un salto a la línea 23.Ahora,
0 < 0
esFalse
, entonces se realiza el salto, que deja la pila con unFalse
valor de retorno para toda la expresión0 < 0 == 0
, aunque la== 0
parte ni siquiera esté marcada.Entonces, para concluir, la respuesta es como se dijo en otras respuestas a esta pregunta.
0 < 0 == 0
Tiene un significado especial. El compilador evalúa esto en dos términos:0 < 0
y0 == 0
. Como con cualquier expresión booleana complejaand
entre ellas, si la primera falla, la segunda ni siquiera está marcada.Espero que esto aclare un poco las cosas, y realmente espero que el método que utilicé para analizar este comportamiento inesperado anime a otros a intentar lo mismo en el futuro.
fuente
Como se mencionó en otros,
x comparison_operator y comparison_operator z
es el azúcar sintáctico(x comparison_operator y) and (y comparison_operator z)
con la ventaja de que y solo se evalúa una vez.Entonces su expresión
0 < 0 == 0
es realmente(0 < 0) and (0 == 0)
, lo que evalúaFalse and True
cuál es la justaFalse
.fuente
Tal vez este extracto de los documentos puede ayudar:
Estas fueron comparaciones, pero como estás encadenando comparaciones , debes saber que:
fuente
Aquí está, en todo su esplendor.
fuente
Estoy pensando que Python está haciendo algo extraño entre la magia. Lo mismo que
1 < 2 < 3
significa que 2 está entre 1 y 3.En este caso, creo que está haciendo [middle 0] es mayor que [left 0] e igual a [right 0]. El medio 0 no es mayor que el izquierdo 0, por lo que se evalúa como falso.
fuente