通常在Python語言中我們判斷兩個字串是否相等的時候,很多同學在初學Python的時候會混用==
和is
,最後造成的結果就是出錯的時候不知道怎麼定位,結果也讓自己意向不到。
下面我們先來看一下==
和is
的表現:
>>> a = 'hello'
>>> b = 'hello'
>>> a is b
True
>>> a == b
True
>>> # 如上情況 is 和 == 的結果一致
>>> a1 = "I'm a long string for code testing"
>>> b1 = "I'm a long string for code testing"
>>> a1 is b1
False
>>> a1 == b1
True
>>> # 如上情況 is 和 == 結果不一致
>>> str1 = "string"
>>> str2 = "".join(['s', 't', 'r', 'i', 'n', 'g'])
>>> str2
'string'
>>> str1 is str2
False
>>> str1 == str2
True
>>> # 如上情況 is 和 == 結果不一致
複製程式碼
為什麼會出現這種情況呢?為什麼在有些情況下is
和==
輸出結果相同有些情況又不同呢?我們簡單做如下分析: 首先通過id()
函式來看看這些變數在記憶體中的具體儲存空間,整理情況如下:
從上圖表格中我們可以看出來is
和==
在驗證兩個字串是否相等的時候表現是不一致的,顯然如果你混用或者誤認為他們是等同的那是存在風險的。
那麼字串的比較到底是用is
還是==
呢,我們來看一下Python官方文件中對兩種操作的說明:
Operation | Syntax | Function |
---|---|---|
Identity | a is b | is_(a, b) |
Equality | a == b | eq(a, b) |
從上可知is
表示的是識別符號(Identity),而==
表示的意思是相等(Equality),顯然兩者不是一個東西。
實際上造成上面輸出結果不一致的根本原因在於is
的作用在於用來檢查物件的識別符號是否一致,也就是說is
是比較兩個物件在記憶體中是否擁有同一塊記憶體空間,它並不適合來判斷兩個字串是否相等。a is b
僅當a和b是同一個物件的時候才返回True, 所以a is b
基本上相當於id(a) == id(b)。
而==
才是真正用來判斷兩個物件的值是否相等的,它實際呼叫的是builtins.py
中的__eq__()
方法,因此a == b
相當於a.__eq__()b
, 所以 ==
操作符可以被過載,而 is
是不能被過載的。
一般情況下如果a is b
為True的話a == b
的值也是True,反之則亦然。 特殊情況除外,如下所示:
>>> a = float('NaN')
>>> a is a
True
>>> a == a
False
複製程式碼
從上面的介紹弄清楚了is
和==
的區別之後,我們再來看圖示表格中的輸出就不難理解了。細心點的同學可能會發現,在表格中a和b的id值一樣,也就是說他們在同一記憶體空間地址中,而a1和b1的id值卻不一樣,這是為什麼呢?這是因為Python中string interning(字串駐留)
機制所決定的: 相對於較小的字串,Python為了提高效能會保留其值的一個副本,當你再次建立這個字串的時候,直接就指向了這個副本,所以'hello'這個字串是在記憶體中有一個副本的,所以a和b的id的值是一樣的;而a1和b1是長字串,並不會駐留,Python在記憶體中分別為a1和b1建立了一個記憶體物件來標識a1和b1,所以這兩個物件擁有相同的內容但是識別符號是不一樣的,所以==
的值為True而is
的值為False。
所以最後總結一下,在Python裡面你要判斷兩個物件是否相等你應該使用==
而不是is。