Olhando para Queue.py no Python 2.6, achei essa construção que achei um pouco estranha:
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
Se maxsize
for 0, a fila nunca estará cheia.
Minha pergunta é como isso funciona para este caso? Como 0 < 0 == 0
é considerado falso?
>>> 0 < 0 == 0
False
>>> (0) < (0 == 0)
True
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
>>> (0) < (0 == 0)
, claramente não é.n = 0 < self.maxsize == self._qsize()
em primeiro lugar, em qualquer idioma. Se seus olhos precisam percorrer a linha várias vezes para descobrir o que está acontecendo, não é uma linha bem escrita. Apenas divida-o em várias linhas.Respostas:
Acredito que o Python tenha um tratamento especial de caso para sequências de operadores relacionais para facilitar a expressão de comparações de intervalo. É muito melhor poder dizer
0 < x <= 5
do que dizer(0 < x) and (x <= 5)
.Estes são chamados comparações encadeadas . E esse é um link para a documentação para eles.
Nos outros casos mencionados, os parênteses forçam um operador relacional a ser aplicado antes do outro e, portanto, não são mais comparações encadeadas. E desde que
True
eFalse
tenha valores como números inteiros, você obtém as respostas das versões entre parênteses.fonte
Porque
é
False
. Você pode encadear operadores de comparação e eles são expandidos automaticamente nas comparações aos pares.EDIT - esclarecimentos sobre True e False em Python
Em Python
True
eFalse
são apenas instâncias debool
, que é uma subclasse deint
. Em outras palavras,True
é realmente apenas 1.O ponto disso é que você pode usar o resultado de uma comparação booleana exatamente como um número inteiro. Isso leva a coisas confusas como
Mas isso só acontecerá se você colocar as comparações entre parênteses para que sejam avaliadas primeiro. Caso contrário, o Python expandirá os operadores de comparação.
fonte
'success' if result_code == 0 else 'failure'
pode ser reescrita('error', 'success')[result_code == 0]
, pois antes disso eu nunca tinha visto um booleano usado para selecionar um item em uma lista / tupla.O comportamento estranho que você experimenta vem da capacidade dos pítons de encadear condições. Como encontra 0 não é menor que 0, decide que a expressão inteira é avaliada como falsa. Assim que você separar isso em condições separadas, você estará alterando a funcionalidade. Inicialmente, ele está essencialmente testando isso
a < b && b == c
para sua declaração original dea < b == c
.Outro exemplo:
fonte
a < b && b == c
é o mesmo quea < b == c
OOEsta é uma comparação encadeada. Retorna true se cada comparação por pares for verdadeira. É o equivalente a
(0 < 0) and (0 == 0)
Isso é equivalente ao
0 < True
que é avaliado como True.Isso é equivalente ao
False == 0
que é avaliado como True.Equivalente ao
0 < True
qual, como acima, avalia como True.fonte
Olhando para a desmontagem (a códigos de bytes), é óbvio porque
0 < 0 == 0
éFalse
.Aqui está uma análise dessa expressão:
Observe as linhas de 0 a 8: essas linhas verificam se o
0 < 0
que obviamente retornaFalse
à pilha python.Agora observe a linha 11:
JUMP_IF_FALSE_OR_POP 23
Isso significa que, se0 < 0
retornos,False
execute um salto para a linha 23.Agora,
0 < 0
éFalse
, então o salto é dado, o que deixa a pilha com umFalse
valor de retorno para toda a expressão0 < 0 == 0
, mesmo que a== 0
parte nem seja verificada.Portanto, para concluir, a resposta é como a dita em outras respostas a essa pergunta.
0 < 0 == 0
tem um significado especial. O compilador avalia isso em dois termos:0 < 0
e0 == 0
. Como em qualquer expressão booleana complexaand
entre elas, se a primeira falhar, a segunda nem será verificada.Espero que isso ilumine um pouco as coisas, e realmente espero que o método que eu usei para analisar esse comportamento inesperado incentive outras pessoas a tentarem o mesmo no futuro.
fonte
Como já
x comparison_operator y comparison_operator z
foi mencionado, o açúcar sintático é(x comparison_operator y) and (y comparison_operator z)
o bônus que y é avaliado apenas uma vez.Portanto, sua expressão
0 < 0 == 0
é realmente(0 < 0) and (0 == 0)
, o que avaliaFalse and True
qual é justoFalse
.fonte
talvez este trecho dos documentos possa ajudar:
Essas foram comparações, mas como você está encadeando comparações, você deve saber que:
fonte
Aqui está em toda a sua glória.
fonte
Eu estou pensando que Python está fazendo isso é estranho entre magia. O mesmo que a
1 < 2 < 3
média 2 está entre 1 e 3.Nesse caso, acho que está fazendo [o meio 0] é maior que [esquerdo 0] e igual a [direito 0]. O meio 0 não é maior que o esquerdo 0, portanto, avalia como falso.
fonte