O que você vê em todas as 3 instâncias é uma consequência da especificação gramatical da linguagem e como os tokens encontrados no código-fonte são analisados para gerar a árvore de análise.
Dar uma olhada neste código de baixo nível deve ajudá-lo a entender o que acontece nos bastidores. Podemos pegar essas instruções python, convertê-las em código de bytes e, em seguida, descompilá-las usando o dis
módulo:
Caso 1: (0, 0) == 0, 0
>>> dis.dis(compile("(0, 0) == 0, 0", '', 'exec'))
1 0 LOAD_CONST 2 ((0, 0))
3 LOAD_CONST 0 (0)
6 COMPARE_OP 2 (==)
9 LOAD_CONST 0 (0)
12 BUILD_TUPLE 2
15 POP_TOP
16 LOAD_CONST 1 (None)
19 RETURN_VALUE
(0, 0)
é primeiro comparado com 0
primeiro e avaliado para False
. Uma tupla é então construída com este resultado e por último 0
, então você obtém (False, 0)
.
Caso 2: 0, 0 == (0, 0)
>>> dis.dis(compile("0, 0 == (0, 0)", '', 'exec'))
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 0 (0)
6 LOAD_CONST 2 ((0, 0))
9 COMPARE_OP 2 (==)
12 BUILD_TUPLE 2
15 POP_TOP
16 LOAD_CONST 1 (None)
19 RETURN_VALUE
Uma tupla é construída com 0
o primeiro elemento. Para o segundo elemento, a mesma verificação é feita como no primeiro caso e avaliada para False
, então você obtém (0, False)
.
Caso 3: (0, 0) == (0, 0)
>>> dis.dis(compile("(0, 0) == (0, 0)", '', 'exec'))
1 0 LOAD_CONST 2 ((0, 0))
3 LOAD_CONST 3 ((0, 0))
6 COMPARE_OP 2 (==)
9 POP_TOP
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
Aqui, como você pode ver, você está apenas comparando essas duas (0, 0)
tuplas e retornando True
.