你真的了解Python的is和==區(qū)別?

下面有段代碼(以下簡稱測試?yán)樱┗肽龋隳茉诓豢创鸢盖闆r下知道運(yùn)行結(jié)果嗎佑力?

a = 1
b = 1
print(a is b) # True
print(a == b) # True
a = 10000
b = 10000
print(a is b) # 有時(shí)True 有時(shí)False
print(a == b) # True
a = -6
b = -6
print(a is b) # 有時(shí)True 有時(shí)False
print(a == b) # True
a = [1, 5]
b = [1, 5]
c = a
print(a is b) # False
print(a == b) # True
print(c is a) # True
print(c == a) # True
print(c is b) # False
print(c == b) # True

概念

在 Python 中,is== 都用于比較筋遭,是分別根據(jù)對象的內(nèi)存地址和對象的值來判斷打颤,所以用途上也不一樣暴拄。

用圖書館的書籍可以打個(gè)值和內(nèi)存地址形象的比喻:

  • 對象的值,就像書籍內(nèi)容:
    • 每本書都有它的內(nèi)容编饺,例如文字乖篷、圖片等,這代表了書的“值”透且。
    • 不同的書可能有相同的內(nèi)容(例如兩本相同的書)撕蔼,但它們?nèi)匀皇遣煌膶?shí)體。
  • 對象的內(nèi)存地址秽誊,書籍在圖書館中的位置:
    • 每本書在圖書館中都有一個(gè)特定的位置鲸沮,比如在某個(gè)書架的某一層某一排。
    • 即使兩本書的內(nèi)容完全相同锅论,如果它們在不同的位置上讼溺,它們就是兩個(gè)不同的對象。

is 身份運(yùn)算符

is 用于比較兩個(gè)對象的身份最易,即比較兩個(gè)對象在內(nèi)存中的地址(內(nèi)存地址可以用Python內(nèi)建函數(shù)id()查看肾胯,它會返回一個(gè)整數(shù))是否相同。換句話說耘纱,它檢查的是兩個(gè)對象是否是同一個(gè)對象敬肚。

回到開頭測試?yán)永铮?/p>

# 注意:以下id函數(shù)計(jì)算出的內(nèi)存地址整數(shù)不一定是代碼的那些整數(shù)
a = 1
b = 1
print(id(a), id(b)) # 輸出:2398302306544 2398302306544
print(a is b) # True,因?yàn)閍和b的id內(nèi)存地址相同束析,所以a和b是同一個(gè)對象

a = [1, 5]
b = [1, 5]
print(id(a), id(b)) # 輸出:2398357892288 2398357883648
print(a is b)  # 輸出: False艳馒,因?yàn)閍和b的id內(nèi)存地址不同,所以a和b是不同的對象员寇,即使它們的值相同

c = a
print(id(a), id(c)) # 輸出:2398357892288 2398357892288
print(a is c)  # 輸出: True弄慰,因?yàn)閏和a的id內(nèi)存地址相同,所以c和a是同一個(gè)對象
== 比較運(yùn)算符

== 用于比較兩個(gè)對象的值是否相等蝶锋。它檢查的是對象的是否相同陆爽,而不是對象本身是否相同(雖然拗口,但事實(shí)如此)扳缕。 這意味著即使是兩個(gè)不同的對象慌闭,只要它們的值相同,== 比較的結(jié)果就是 True躯舔。

a = 1
b = 1
print(a == b)  # 輸出: True驴剔,因?yàn)?a 和 b 的值相同

a = [1, 5]
b = [1, 5]
c = a
print(a == b)  # 輸出: True,因?yàn)?a 和 b 的值相同
print(c == b)  # 輸出: True粥庄,因?yàn)?c 和 b 的值相同

通常情況下丧失,== 可以通過重載 __eq__ 方法來定義值比較行為, 再舉回書籍的例子,我們用書籍內(nèi)容content來表示對象的值惜互,location不是內(nèi)存地址

class Book:
    def __init__(self, location, content):
        self.location = location
        self.content = content

    def __eq__(self, other):
        if isinstance(other, Book):
            return self.content == other.content
        return False

    def __repr__(self):
        return f"Book(content='{self.content}')"

# 創(chuàng)建兩個(gè) Book 對象
book1 = Book(location="A", content="Hello")
book2 = Book(location="B", content="Hello")
book3 = Book(location="C", content="Hi")

# 比較對象
print(book1 == book2)  # 輸出: True布讹,因?yàn)?content 相同
print(book1 == book3)  # 輸出: False琳拭,因?yàn)?content 不同

# 查看對象內(nèi)存地址,不同的對象
print(id(book1)) # 輸出: 1907430631760
print(id(book2)) # 輸出: 1907430632240
print(id(book3)) # 輸出: 1907430632336

注意

共用緩存對象

你也許發(fā)現(xiàn)了is在某些情況下判斷并不穩(wěn)定描验,比如測試?yán)又?code>a白嘁、b都等于10000(或-6)時(shí),a is b有時(shí)候會等于False挠乳,有時(shí)候會等于True

這主要是因?yàn)?code>Python對于一些小整數(shù)(通常在-5256之間姑躲,范圍并不是固定)和一些字符串進(jìn)行了緩存睡扬,所以這些對象在內(nèi)存中會被重用。 當(dāng)比較這些小整數(shù)和字符串時(shí)黍析,is 比較時(shí)可能返回 True卖怜,即使你認(rèn)為它們是不同的對象。

所以涉及到這些對象進(jìn)行比較時(shí)阐枣,一般不用is而是==马靠。

單例模式

在單例模式下,所有構(gòu)造出來的對象實(shí)際上都是同一個(gè)實(shí)例蔼两,因此使用 is== 進(jìn)行比較時(shí)甩鳄,結(jié)果都應(yīng)該是 True,但一般都是用is來判斷额划。

這是因?yàn)槭褂?is 來判斷更加直觀和高效妙啃, is比較的是對象的身份(即內(nèi)存地址),而 == 比較的是對象的值俊戳,要先找到地址才能找到值揖赴,而且某些值比較時(shí)需要進(jìn)行額外計(jì)算消耗資源(參考找書籍的例子)。

在python中有些比較特殊的對象如None抑胎、True燥滑、False等,它們都是個(gè)單例對象阿逃,所以通常判斷一個(gè)變量是否為這些對象時(shí)應(yīng)該使用 is 而不是 ==铭拧。

應(yīng)用場景

  • is主要用于判定是不是同一個(gè)對象,在與單例對象比較時(shí)恃锉,一般都是有is來判斷
  • ==通常是用于兩個(gè)對象確切的值的比較羽历,比如字符串比較,數(shù)值比較淡喜。

總結(jié)

  • ==:比較兩個(gè)對象的值是否相等秕磷。
  • is:比較兩個(gè)對象的身份(內(nèi)存地址)是否相同。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炼团,一起剝皮案震驚了整個(gè)濱河市澎嚣,隨后出現(xiàn)的幾起案子疏尿,更是在濱河造成了極大的恐慌,老刑警劉巖易桃,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件褥琐,死亡現(xiàn)場離奇詭異,居然都是意外死亡晤郑,警方通過查閱死者的電腦和手機(jī)敌呈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來造寝,“玉大人磕洪,你說我怎么就攤上這事〗肓” “怎么了析显?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長签赃。 經(jīng)常有香客問我谷异,道長,這世上最難降的妖魔是什么锦聊? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任歹嘹,我火速辦了婚禮,結(jié)果婚禮上孔庭,老公的妹妹穿的比我還像新娘荞下。我一直安慰自己,他們只是感情好史飞,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布尖昏。 她就那樣靜靜地躺著,像睡著了一般构资。 火紅的嫁衣襯著肌膚如雪抽诉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天吐绵,我揣著相機(jī)與錄音迹淌,去河邊找鬼。 笑死己单,一個(gè)胖子當(dāng)著我的面吹牛唉窃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纹笼,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼纹份,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蔓涧,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤件已,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后元暴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體篷扩,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年茉盏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鉴未。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸠姨,死狀恐怖铜秆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情享怀,我是刑警寧澤羽峰,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布趟咆,位于F島的核電站添瓷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏值纱。R本人自食惡果不足惜鳞贷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望虐唠。 院中可真熱鬧搀愧,春花似錦、人聲如沸疆偿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杆故。三九已至迅箩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間处铛,已是汗流浹背饲趋。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撤蟆,地道東北人奕塑。 一個(gè)月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像家肯,于是被迫代替她去往敵國和親龄砰。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容