Skip to content

[Python] 小知識:== 和 is 的差異

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


Read More

Tags:

Leave a Reply