python之比較is與==(轉載)
在 Python 中會用到物件之間比較,可以用 ==,也可以用 is 。但是它們的區別是什麼呢?
is 比較的是兩個例項物件是不是完全相同,它們是不是同一個物件,佔用的記憶體地址是否相同。萊布尼茨說過:“世界上沒有兩片完全相同的葉子”,這個is正是這樣的比較,比較是不是同一片葉子(即比較的id是否相同,這id類似於人的身份證標識)。
== 比較的是兩個物件的內容是否相等,即記憶體地址可以不一樣,內容一樣就可以了。這裡比較的並非是同一片葉子,可能葉子的種類或者脈絡相同就可以了。預設會呼叫物件的 eq()方法。
可以通過如下例子來區分比較下:
a = ["I", "love", "Python"]
b = a
a的引用複製給b,在記憶體中其實是指向了用一個物件
b is a
True
id(a)
46381384
id(b)
46381384
當然,內容也肯定是相等的
b == a
True
可以發現b和a的記憶體地址是相同的,它們指向同一塊記憶體,因而 is 和 == 的結果都為True。這是因為直接賦值都是賦值的引用,是引用,是引用,重要的事情說三遍。但如果不是通過引用賦值,而是通過切片賦值呢?
b通過切片操作重新分配了物件,但是值和a相同
b = a[:]
b is a
False
id(a)
48740680
id(b)
48740680
b == a # 但他們的值還是相等的
True
新建物件之後,b 和 a 指向了不同的記憶體,所以 b is a 的結果為False,而 b==a的結果為True。在這裡,小編提一個問題,b[0] is a[0] 的結果呢?
答案是True。因為切片拷貝是淺拷貝,列表中的元素並未重新建立。不理解的同學請翻看之前的文章 Python中的淺拷貝與深拷貝。
通常,我們關注的是值,而不是記憶體地址,因此 Python 程式碼中 == 出現的頻率比 is 高。但是什麼時候用 is 呢?
is 與 == 相比有一個比較大的優勢,就是計算速度快,因為它不能過載,不用進行特殊的函式呼叫,少了函式呼叫的開銷而直接比較兩個整數 id。而 a == b 則是等同於a.__eq__(b)。繼承自 object 的 eq 方法比較兩個物件的id,結果與 is 一樣。但是多數Python的物件會覆蓋object的 __eq__方法,而定義內容的相關比較,所以比較的是物件屬性的值。
在變數和單例值之間比較時,應該使用 is。目前,最常使用 is 的地方是判斷物件是不是 None。下面是推薦的寫法:
a is None
判斷不是None的推薦寫法是:
a is not None
Python會對比較小的整數物件進行快取,下次用的時候直接從快取中獲取,所以is 和 == 的結果可能相同:
a = 1
b = 1
a is b
True
a == b
True
而看一下另外一段程式碼:
a = 257
b = 257
a is b
False
這是什麼原因呢?
注意,Python僅僅對比較小的整數物件進行快取(範圍為範圍[-5, 256])快取起來,而並非是所有整數物件。需要注意的是,這僅僅是在命令列中執行,而在Pycharm或者儲存為檔案執行,結果是不一樣的,這是因為直譯器做了一部分優化。
總結
1、is 比較兩個物件的 id 值是否相等,是否指向同一個記憶體地址;
2、== 比較的是兩個物件的內容是否相等,值是否相等;
3、小整數物件[-5,256]在全域性直譯器範圍內被放入快取供重複使用;
4、is 運算子比 == 效率高,在變數和None進行比較時,應該使用 is。