unary - python>'




為什麼在Python中0,0==(0,0)等於(0,False) (4)

前兩個表達式都解析為元組:

  1. (0, 0) == 0 (這是 False ),然後是 0
  2. 0 ,然後是 0 == (0, 0) (這種方式仍然是 False )。

表達式以這種方式拆分,因為逗號分隔符與相等運算符相比具有相對優先級:Python看到包含兩個表達式的元組,其中一個恰好是相等測試,而不是兩個元組之間的相等測試。

但是在你的第三個例子中, a = 0, 0 不能 是一個元組。 元組是值的集合,與等式測試不同,賦值在Python中沒有任何價值。 賦值不是表達式,而是聲明; 它沒有可以包含在元組或任何其他周圍表達式中的值。 如果您嘗試類似 (a = 0), 0 以強制解釋為元組,則會出現語法錯誤。 這樣就可以將一個元組賦值給一個變量 - 通過將其寫為 a = (0, 0) - 可以更明確地將其 a = (0, 0) 的唯一有效解釋。

在Python中(我只使用Python 3.6進行了檢查,但我相信它應該適用於許多以前的版本):

(0, 0) == 0, 0   # results in a two element tuple: (False, 0)
0, 0 == (0, 0)   # results in a two element tuple: (0, False)
(0, 0) == (0, 0) # results in a boolean True

但:

a = 0, 0
b = (0, 0)
a == b # results in a boolean True

為什麼兩種方法的結果不同? 相等運算符是否以不同方式處理元組?


另一種解釋問題的方法:你可能熟悉字典文字

{ "a": 1, "b": 2, "c": 3 }

和數組文字

[ "a", "b", "c" ]

和元組文字

( 1, 2, 3 )

但是你沒有意識到的是,與字典和數組文字不同,你通常在元組文字周圍看到的括號 不是文字語法的一部分 。 元組的文字語法只是由逗號分隔的表達式序列:

1, 2, 3

Python中正式語法 語言中的“exprlist”)。

現在,您對數組文字的期望是什麼?

[ 0, 0 == (0, 0) ]

評價到? 這可能看起來更像它 應該 是相同的

[ 0, (0 == (0, 0)) ]

當然評估為 [0, False] 。 同樣,使用明確括號的元組文字

( 0, 0 == (0, 0) )

獲得 (0, False) 並不奇怪。 但括號是可選的;

0, 0 == (0, 0)

是一回事。 這就是你得到的原因 (0, False)

如果你想知道 為什麼 圍繞一個元組文字的括號是可選的,那很大程度上是因為以這種方式編寫解構賦值會很煩人:

(a, b) = (c, d) # meh
a, b = c, d     # better

在第一篇中,Python正在製作兩個元組的元組:

  1. 表達式 (0, 0) == 0 ,計算結果為 False
  2. 常數 0

在第二個方面,它是另一種方式。


您在所有3個實例中看到的是語言的 語法規範 的結果,以及如何解析源代碼中遇到的令牌以生成解析樹。

看一下這個低級代碼應該可以幫助您了解幕後發生的事情。 我們可以使用這些python語句,將它們轉換為字節代碼,然後使用 dis 模塊對它們進行反編譯:

情況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) 首先與 0 進行比較,並將其評估為 False 。 然後用這個結果構造一個元組並且為 0 ,所以得到 (False, 0)

案例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

構造元組,其中 0 作為第一個元素。 對於第二個元素,完成與第一個案例相同的檢查併計算為 False ,因此得到 (0, False)

案例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

在這裡,如您所見,您只是比較這兩個 (0, 0) 元組並返回 True







operator-precedence