To, co widzisz we wszystkich trzech przypadkach, jest konsekwencją specyfikacji gramatycznej języka i sposobu, w jaki tokeny napotkane w kodzie źródłowym są analizowane w celu wygenerowania drzewa parsowania.
Spojrzenie na ten kod niskiego poziomu powinno pomóc ci zrozumieć, co dzieje się pod maską. Możemy wziąć te instrukcje Pythona, przekonwertować je na kod bajtowy, a następnie zdekompilować za pomocą dis
modułu:
Przypadek 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)
jest najpierw porównywany z 0
pierwszym i oceniany do False
. Następnie tworzona jest krotka z tym wynikiem i ostatnim 0
, więc otrzymujesz (False, 0)
.
Przypadek 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
Krotka jest konstruowana z 0
pierwszym elementem. W przypadku drugiego elementu wykonywane jest to samo sprawdzenie, co w pierwszym przypadku i oceniane False
, więc otrzymujesz (0, False)
.
Przypadek 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
Tutaj, jak widzisz, po prostu porównujesz te dwie (0, 0)
krotki i zwracasz True
.