【Python】隨記:資料的值比較時用「==」和「is」的差異

資料比較是程式語言的基礎,但是各語言的用法和一些細節不太一樣。

像是在python中使用==is都可以比對字串(或是!=is not),但是一個是比對值,一個是比對記憶體位置。究竟要在何時使用呢?讓我們看下去。

在字串比較中,可以使用「==」,但有時使用「is」(或是用「!=」和「is not」),像是我們使用字串比較

a = "eyelash"
b = a
c = "eyelash"

print(a == b) #會是True
print(a == c) #會是True
print(a == c) #會是True
print(b == a) #會是True

會發現「==」和「is」完全沒有差異。那到底為什麼要分成兩種不同寫法呢?這時改用陣列,就有不同的結果:

a = ["eyelash","test"] #定義一個陣列
c = ["eyelash","test"] #定義相同內容的陣列

print(a == c) # 結果會是True
print(a is c) # 結果會是False

結果會是不同的,到底為何會這樣?

原來「==」是比較運算子(Comparison operators),像是><!=等等,都是相同的一類;而「is」是身分運算子(Identity operators),他則是與is not一組。

他們差別就是在不同的運算子中,比較運算子是比對兩者的值是否相同,就好像1+1是否等於2,這樣的值比較。但是身分運算子就不同,他是做身分的比較,也就是比對是否為相同的物件,是否在記憶體相同的位置,也就是使用id()(詳細說明參考:文件)看看是否相同。

像第一個範例,都是字串eyelash,他們的記憶體位置為(使用id("eyelash")):4439806512,因此無論是值都是「eyelash」,而記憶體位置也是相同的,所以兩個運算子結果都是True

第二的範例中,改成陣列。內容相同,因此在比較運算子==的判斷,也會相同;但是在身分運算子is下,他們是不同的記憶體位置,所以就是不同的結果。這會在記憶體參考的物件,像是陣列[]或是字典dict等等有不同的效果,在使用上不得不注意。


同場加映:

無意間發現有趣現象:

a = ["eyelash","test"] # 與第二個範例相同
c = ["eyelash","test"] # 與第二個範例相同

print(f"a[0] is c[0] => [{a is c}]") # 結果是: a[0] is c[0] => [False] 
print(f"a[0] is c[0] => [{a[0] is c[0]}]") # 結果是: a[0] is c[0] => [True] 

明明上面說,使用陣列[]是不同的記憶體位置,第一個print顯示也是False,但為什麼在取裡面的值時,卻比對是True,連a[1] is c[1]也是True,不就全部都是True了嗎?

為了驗證是否如我想,使用id()的方式查,發現原來相同文字的值都是相同位置,但是陣列主體卻是不同的:

id(a) # 結果是:4438986416
id(c) # 結果是:4439810448
a is c # 結果是:False

id(a[0]) # 結果是:4439806512
id(c[0]) # 結果是:4439806512
a[0] is c[0] # 結果是:True

id("eyelash") # 結果是:4439806512
a[0] is "eyelash" # 結果是:True
c[0] is "eyelash" # 結果是:True

陣列他們兩個主體不同,記憶體位置不同,由於他們的值都是「eyelash」,為了節省空間,所以相同的值都導向相同記憶體,因此才會a is cFalse,但是a[0]卻和c[0]卻相同。

 


參考資料:


 

~Copyright by Eyelash500~

技術文章:EY*研究院
iT邦幫忙:eyelash*睫毛
Blog:睫毛*Relax
Facebook:睫毛*Relax