當前位置:
首頁 > 知識 > Python 解惑:整數比較

Python 解惑:整數比較

(點擊

上方藍字

,快速關注我們)




來源:伯樂在線/劉志軍 ,微信公號:Python之禪(ID:VTtalk)


foofish.net/python-int-mystery.html


如有好文章投稿,請點擊 → 這裡了解詳情




在 Python 中一切都是對象,毫無例外整數也是對象,對象之間比較是否相等可以用==,也可以用is。==和is操作的區別是:





  • is比較的是兩個對象的id值是否相等,也就是比較倆對象是否為同一個實例對象,是否指向同一個內存地址。



  • ==比較的是兩個對象的內容是否相等,默認會調用對象的__eq__()方法。




清楚is和==的區別之後,對此也許你有可能會遇到下面的這些困惑,於是就有了這樣一篇文章,試圖把Python中一些隱晦的東西趴出來,希望對你有一定的幫助。我們先來看兩段代碼:




片段一:





>>>

a

=

256


>>>

b

=

256


>>>

a

==

b


True


>>>



片段二:





>>>

a

=

256


>>>

b

=

256


>>>

a

is

b


True


>>>




在互動式命令行執行上面兩段代碼,代碼片段一中的a==b返回True很好理解,因為兩個對象的值都是256,對於片段二,a is b也返回True,這說明a和b是指向同一個對象的,可以檢查一下他們的id值是否相等:




>>>

id

(

a

)


8213296

>>>

id

(

b

)


8213296


>>>




結果證明他倆的確是同一個對象,指向的是同一個內存地址。那是不是所有的整數對象只要兩個對象的值(內容)相等,它們就是同一個實例對象呢?換句話說,對於整數對象只要==返回True,is操作也會返回True嗎?帶著這個問題來看下面這兩段代碼:




片段一:





>>>

a

=

257


>>>

b

=

257


>>>

a

==

b


True


>>>




片段二:





>>>

a

=

257


>>>

b

=

257


>>>

a

is

b


False


>>>




對於257,a is b返回的竟然是False,結果可能在你的意料之中,也有可能出乎你的意料,但不管怎麼,我們還是要刨根問底,找出問題的真相。




解惑一




出於對性能的考慮,Python內部做了很多的優化工作,對於整數對象,Python把一些頻繁使用的整數對象緩存起來,保存到一個叫small_ints的鏈表中,在Python的整個生命周期內,任何需要引用這些整數對象的地方,都不再重新創建新的對象,而是直接引用緩存中的對象。Python把這些可能頻繁使用的整數對象規定在範圍[-5, 256]之間的小對象放在small_ints中,但凡是需要用些小整數時,就從這裡面取,不再去臨時創建新的對象。因為257不再小整數範圍內,因此儘管a和b的值是一樣,但是他們在Python內部卻是以兩個獨立的對象存在的,各自為政,互不干涉。




弄明白第一個問題後,我們繼續在Python互動式命令行中寫一個函數,再來看下面這段代碼:




片段一:





>>>

c

=

257


>>>

def

foo

()

:


...

a

=

257


...

b

=

257


...

print

a

is

b


...

print

a

is

c


...


>>>

foo

()


True


False




呃,什麼情況,是的,你沒看錯,片段一中的這段代碼 a、b 值都是257的情況下,出現了a is b返回True,而a is c 返回的False,a、b、c的值都為257,為什麼會出現不同的結果呢?這對於剛剛好不容易建立起來的認知就被徹底否決了嗎,那這段代碼中究竟發生了什麼?難道解惑一中的結論是錯誤的嗎?




解惑二





A Python program is constructed from code blocks. A block is a piece of Python program text that is executed as a unit. The following are blocks: a module, a function body, and a class definition. Each command typed interactively is a block. A script file (a file given as standard input to the interpreter or specified as a command line argument to the interpreter) is a code block. A script command (a command specified on the interpreter command line with the 『-c『 option) is a code block. structure-of-a-program




為了弄清楚這個問題,我們有必要先理解程序代碼塊的概念。Python程序由代碼塊構成,代碼塊作為程序的一個最小基本單位來執行。一個模塊文件、一個函數體、一個類、互動式命令中的單行代碼都叫做一個代碼塊。在上面這段代碼中,由兩個代碼塊構成,c = 257作為一個代碼塊,函數foo作為另外一個代碼塊。Python內部為了將性能進一步的提高,凡是在一個代碼塊中創建的整數對象,如果存在一個值與其相同的對象於該代碼塊中了,那麼就直接引用,否則創建一個新的對象出來。

Python出於對性能的考慮,但凡是不可變對象,在同一個代碼塊中的對象,只有是值相同的對象,就不會重複創建,而是直接引用已經存在的對象。

因此,不僅是整數對象,還有字元串對象也遵循同樣的原則。所以 a is b就理所當然的返回True了,而c和a不在同一個代碼塊中,因此在Python內部創建了兩個值都是257的對象。為了驗證剛剛的結論,我們可以借用dis模塊從位元組碼的角度來看看這段代碼。





>>>

import

dis


>>>

dis

.

dis

(

foo

)


2

0

LOAD

_

CONST

1

(

257

)


3

STORE

_

FAST

0

(

a

)



3

6

LOAD

_

CONST

1

(

257

)


9

STORE

_

FAST

1

(

b

)



4

12

LOAD

_

FAST

0

(

a

)


15

LOAD

_

FAST

1

(

b

)


18

COMPARE

_

OP

8

(

is

)


21

PRINT

_

ITEM


22

PRINT

_

NEWLINE



5

23

LOAD

_

FAST

0

(

a

)


26

LOAD

_

GLOBAL

0

(

c

)


29

COMPARE

_

OP

8

(

is

)


32

PRINT

_

ITEM


33

PRINT

_

NEWLINE


34

LOAD

_

CONST

0

(

None

)


37

RETURN_VALUE




可以看出兩個257都是從常量池的同一個位置co_consts[1]獲取的。




總結




一番長篇大論之後,得出兩點結論:1、小整數對象[-5,256]是全局解釋器範圍內被重複使用,永遠不會被GC回收。2、同一個代碼塊中的不可變對象,只要值是相等的就不會重複創建新的對象。似乎這些知識點對日常的工作一點忙也幫不上,因為你根本不會用is來比較兩個整數對象的值是否相等。那為什麼還要拿出來討論呢?嗯,程序員學知識,不應該淺嘗輒止,要充分發揮死磕到底的精神。




看完本文有收穫?請轉

發分享給更多人


關注「P

ython開發者」,提升Python技能


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python 的精彩文章:

兄弟連Python培訓:一分耕耘,一分收穫——廣州兄弟連
2分鐘理清計算機、Python和Pip的三角關係
iOS程序員如何使用Python寫網路爬蟲
【Python爬蟲實戰】爬取糗事百科段子
我用 Python 和 Twilio 實現自動化選課

TAG:Python |

您可能感興趣

Kafka解惑之Old Producer(2)——Sync Analysis
Simple Journey紐西蘭遊學答疑解惑
Spring 事務配置解惑
解惑:不止iPhone,連HUAWEI、OPPO等廠商都在取消耳機孔,意義何在?
解惑7問 vivo X20Plus屏幕指紋版初體驗
我們有了可重複使用的火箭,但為什麼還沒有會飛的汽車?「Rodney Brooks」法則為你解惑
小白解惑:阿迪Boost到底是啥?
壽司之神必知的那些經營秘訣《Sushi Bar》為你逐個解惑
要不要給Mac 加塊外置顯卡 WWDC之後的答疑解惑
vivo屏下指紋小解惑,具體表現如何?
遊戲角色缺少生命力?日本konami知名製作人與國內遊戲大咖給你解惑
櫻通商答疑解惑,日本留學考試EJU和JUPE的區別
Redmi不是紅米?紅米官微:3月18日「解惑」
你家的智能門鎖真的安全嗎?TechWeb專訪鎖匠專家為您解惑
紅米K20 Pro能打過小米9?這篇文章將為你解惑
《復聯3:無限戰爭》導演解惑:滅霸vs浩克誰比較強悍
最新調研:解惑MLCC九重心事
用手機聽音樂卻莫名換了歌曲?聯想Z6Pro的這一招幫你輕鬆解惑!
聚焦GERD臨床難點,解惑促動力葯使用
X-T3和X-T30到底怎麼選?好機友攝影為你解惑