Por que (1 em [1,0] == Verdadeiro) é avaliado como Falso?

153

Quando eu estava procurando respostas para essa pergunta , descobri que não entendia minha própria resposta.

Eu realmente não entendo como isso está sendo analisado. Por que o segundo exemplo retorna Falso?

>>> 1 in [1,0]             # This is expected
True
>>> 1 in [1,0] == True     # This is strange
False
>>> (1 in [1,0]) == True   # This is what I wanted it to be
True
>>> 1 in ([1,0] == True)   # But it's not just a precedence issue!
                           # It did not raise an exception on the second example.

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    1 in ([1,0] == True)
TypeError: argument of type 'bool' is not iterable

Obrigado por qualquer ajuda. Eu acho que devo estar perdendo algo realmente óbvio.


Eu acho que isso é sutilmente diferente do duplicado vinculado:

Por que a expressão 0 <0 == 0 retorna False em Python? .

Ambas as questões têm a ver com a compreensão humana da expressão. Parecia haver duas maneiras (na minha opinião) de avaliar a expressão. É claro que nenhum dos dois estava correto, mas no meu exemplo, a última interpretação é impossível.

Olhando para 0 < 0 == 0você , você pode imaginar cada metade sendo avaliada e fazendo sentido como uma expressão:

>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True

Portanto, o link responde por que isso avalia False:

>>> 0 < 0 == 0
False

Mas com o meu exemplo 1 in ([1,0] == True)não faz sentido como expressão, então, em vez de haver duas interpretações possíveis (reconhecidamente erradas), apenas uma parece possível:

>>> (1 in [1,0]) == True
Peter Wood
fonte
1
Precedência do operador ... as ==ligações são mais apertadas do que in, portanto, [1,0] == Truesão avaliadas primeiro, depois o resultado disso é alimentado 1 in other_result.
Marc B
Eu removi a tag Python-2.7, já que o Python 3.2 se comporta da mesma maneira.
Lvc
1
@ Marc B: Não explica a segunda expressão
Scott Hunter
32
@ MarcB, a pergunta incluía um teste usando parênteses para refutar essa interpretação.
Mark Ransom

Respostas:

194

Python realmente aplica operador de comparação encadeado aqui. A expressão é traduzida para

(1 in [1, 0]) and ([1, 0] == True)

o que é obviamente False.

Isso também acontece para expressões como

a < b < c

que se traduz em

(a < b) and (b < c)

(sem avaliar bduas vezes).

Veja a documentação da linguagem Python para mais detalhes.

Sven Marnach
fonte
40
Prova adicional para isso, 1 in [1, 0] == [1, 0]avalia para True.
Andrew Clark
9
Há muito tempo penso nisso como uma verruga de linguagem. Eu teria preferido que o inoperador tivesse uma precedência mais alta do que outros operadores de comparação e que não estivesse em cadeia. Mas talvez esteja faltando um caso de uso.
Steven Rumbalski
3
boa pegada, eu nem pensei nisso. Não faz muito sentido para permitir o encadeamento de in- apesar de tudo x < y < zfaz sentido, mas não tanto comx in y in z
BlueRaja - Danny Pflughoeft
7
@Ven útil: talvez. Legível: definitivamente não. O Python pretende imitar a tipografia matemática comum com essa convenção, mas quando usado com inisso simplesmente não é mais o caso e o torna bastante contra-intuitivo.
Konrad Rudolph
6
@ KonradRudolph: Eu já vi pensamentos como "1 ≤ x ∈ ℝ" em textos matemáticos mais de uma vez, mas basicamente concordo com você.
Sven Marnach 15/02/12