Last Updated on 2021-08-01 by Clay
在 Python 中,很多人會在 ==
和 is
這兩種用法上混淆,實際上兩者之間的用法也是真的非常相似,比方說以下這樣的例子:
>>> a = 5 >>> b = 5 >>> a == b True
看起來是理所當然相等的,對吧?那麼使用 is
的情況呢?
>>> a = 5 >>> b = 5 >>> a is b True
也是一樣的結果!這也導致了很多人因此以為 ==
和 is
是相同的用法,只是寫法的不同。
但其實不是這樣子的;我們來看段 ==
和 is
結果不同的程式碼:
>>> a = 1000 >>> b = 1000 >>> a == b True >>> a is b False
可以發現,在 a 和 b 在賦值 1000 之後,==
和 is
便不再是相同的結果了。
這是為什麼呢?這裡得稍微提到一下 Python 中的 id()
函式。
id() 是什麼呢?
在 CPython 中,id()
可以被簡單地認為是一個專門用於查看目標對象的『記憶體位址』,比方說以下這樣的範例:
>>> target = 100 >>> id(target) 10917664
我們可以想像每一個變數,都有著自己的『變數名稱』、『值』、『記憶體位址』...... 等等的屬性。而這也是 ==
和 is
有所差異的地方。
== 和 is 的差異
我們再來看一下剛才的程式,並加上 id()
查看記憶體位址。
>>> a = 1000 >>> b = 1000 >>> id(a) 140042294421360 >>> id(b) 140042294420272 >>> a == b True >>> a is b False
這樣就能看出 == 和 is 最大的不同了:
==
是判斷兩個變數之間的『值』是否相同is
是判斷兩個變數之間的『記憶體位址』是否相同。
不過這樣一來,一開始的程式碼怎麼解釋呢?
>>> a = 5 >>> b = 5 >>> a == b True >>> a is b True
==
和 is
的返回值都一樣啊?
這是因為在 Python 中,在到 -5 ~ 256 的數值都是固定的記憶體位址,可以直接開兩個終端機分別看看,無論如何都是固定的,很有趣!不過從 257 開始,每個值都會有其申請的記憶體位址,也就是說每次都會不一樣。
例外情況
順帶一提,如果使用『a 賦值給 b』這樣的方法的話,即使 a 和 b 的數值都超過 256,其記憶體位址也會相同,以下看個簡單的範例:
>>> a = 1000 >>> b = a >>> a is b True
所以在撰寫程式、尤其是判斷式的時候一定要小心,很容易不小心就出錯了。
另外,以上所提及的,全都是在互動界面時撰寫程式的情況。若是在開發環境中,經常是直接撰寫程式碼,寫好後再由直譯器 (Interpreter) 執行 —— 在這樣的情況下,執行過程中會針對所謂的『基本資料型態』進行 Cache (快取) 的優化,這樣會導致初始化時變數賦予同樣的值會有相同的記憶體位址。
比方說,我在終端機中開啟一個新的檔案:
vim test.py
然後在開啟的 test.py
中寫下:
# coding: utf-8 # Init a = 1000 b = 1000 # Id print('a id:', id(a)) print('b id:', id(b)) # == & is print('==:', a == b) print('is:', a is b)
Output:
a id: 140547554998224
b id: 140547554998224
==: True
is: True
大致上,==
和 is
容易碰到的誤區就是這些,希望我也不會再踩到這樣的坑。
References
- http://net-informations.com/python/iq/is.htm
- https://www.geeksforgeeks.org/difference-operator-python/
- https://stackoverflow.com/questions/132988/is-there-a-difference-between-and-is
- https://realpython.com/python-is-identity-vs-equality/