在 Python 中會用到對象之間比較,能夠用 ==,也能夠用 is 。可是它們的區別是什麼呢?python
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] 的結果呢?code
答案是True。由於切片拷貝是淺拷貝,列表中的元素並未從新建立。不理解的同窗請翻看以前的文章 python中的淺拷貝和深拷貝。
對象
一般,咱們關注的是值,而不是內存地址,所以 Python 代碼中 == 出現的頻率比 is 高。可是何時用 is 呢?繼承
is 與 == 相比有一個比較大的優點,就是計算速度快,由於它不能重載,不用進行特殊的函數調用,少了函數調用的開銷而直接比較兩個整數 id。而 a == b 則是等同於a.__eq__(b)。繼承自 object 的 __eq__ 方法比較兩個對象的id,結果與 is 同樣。可是多數Python的對象會覆蓋object的 __eq__方法,而定義內容的相關比較,因此比較的是對象屬性的值。內存
在變量和單例值之間比較時,應該使用 is。目前,最常使用 is 的地方是判斷對象是否是 None。下面是推薦的寫法:get
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或者保存爲文件執行,結果是不同的,這是由於解釋器作了一部分優化。
總結
一、is 比較兩個對象的 id 值是否相等,是否指向同一個內存地址;二、== 比較的是兩個對象的內容是否相等,值是否相等;三、小整數對象[-5,256]在全局解釋器範圍內被放入緩存供重複使用;四、is 運算符比 == 效率高,在變量和None進行比較時,應該使用 is。