在 python 中一切都是物件,整數也是物件,在比較兩個整數時有兩個運算子==
和is
,它們的區別是:
知道了is
和==
的區別之後,我們可以來看看下面的**,了解python中整數比較有哪些坑:
def
main()
: x = y =-1
while
true
: x +=
1 y +=
1if x is y:
print
('%d is %d'
%(x, y)
)else
:print
('attention! %d is not %d'
%(x, y)
)break
x = y =
0while
true
: x -=
1 y -=
1if x is y:
print
('%d is %d'
%(x, y)
)else
:print
('attention! %d is not %d'
%(x, y)
)break
if __name__ ==
'__main__'
: main(
)
上面**的部分執行結果如下圖所示,出現這個結果的原因是python出於對效能的考慮所做的一項優化。對於整數物件,python把一些頻繁使用的整數物件快取起來,儲存到乙個叫small_ints
的鍊錶中,在python的整個生命週期內,任何需要引用這些整數物件的地方,都不再重新建立新的物件,而是直接引用快取中的物件。python把頻繁使用的整數物件的值定在[-5, 256]這個區間,如果需要這個範圍的整數,就直接從small_ints
中獲取引用而不是臨時建立新的物件。因為大於256或小於-5的整數不在該範圍之內,所以就算兩個整數的值是一樣,但它們是不同的物件。
當然僅僅如此這個坑就不值一提了,如果你理解了上面的規則,我們就再看看下面的**。
import dis
a =257
defmain()
: b =
257# 第6行
c =257# 第7行
print
(b is c)
# true
print
(a is b)
# false
print
(a is c)
# false
if __name__ ==
"__main__"
: main(
)
程式的執行結果已經用注釋寫在**上了。夠坑吧!看上去a
、b
和c
的值都是一樣的,但是is
運算的結果卻不一樣。為什麼會出現這樣的結果,首先我們來說說python程式中的**塊。所謂**塊是程式的乙個最小的基本執行單位,乙個模組檔案、乙個函式體、乙個類、互動式命令中的單行**都叫做乙個**塊。上面的**由兩個**塊構成,a = 257
是乙個**塊,main
函式是另外乙個**塊。python內部為了進一步提高效能,凡是在乙個**塊中建立的整數物件,如果值不在small_ints
快取範圍之內,但在同乙個**塊中已經存在乙個值與其相同的整數物件了,那麼就直接引用該物件,否則建立乙個新的物件出來,這條規則對不在small_ints
範圍的負數並不適用,對負數值浮點數也不適用,但對非負浮點數和字串都是適用的,這一點讀者可以自行證明。所以b is c
返回了true
,而a
和b
不在同乙個**塊中,雖然值都是257,但卻是兩個不同的物件,is
運算的結果自然是false
了。
為了驗證剛剛的結論,我們可以借用dis
模組(聽名字就知道是進行反彙編的模組)從位元組碼的角度來看看這段**。如果不理解什麼是位元組碼,可以先看看《談談 python 程式的執行原理》這篇文章。可以先用import dis
匯入dis
模組並按照如下所示的方式修改**。
if __name__ ==
"__main__"
: main(
) dis.dis(main)
**的執行結果如下圖所示。可以看出**第6行和第7行,也就是main
函式中的257是從同乙個位置載入的,因此是同乙個物件;而**第9行的a
明顯是從不同的地方載入的,因此引用的是不同的物件。
如果還想對這個問題進行進一步深挖,推薦大家閱讀《python整數物件實現原理》這篇文章。
Python解惑 整數比較
python 中常用的資料型別bool 布林 型別的例項物件 值 就兩個,真和假,分別用true和false表示。在if 條件判斷和while 語句中經常用到,不過在python2.x 中,true 和false 卻有著奇怪的用法,就是真假可以相互被替換,先看下面 true true false f...
Python 整數物件is比較
python 整數用is比較 is 比較的是兩個物件的id值 記憶體中的位址 5,256 之間常用整數對比 在比較整數時,要知道python對於常用整數的儲存,5,256 之間的整數是存放在快取中的鍊錶中,需要使用時不再建立新的物件,而是直接引用物件 通過以下 可以看到區別 a 10 b 10 a ...
python類整數 整數類python
sinteger類基於位列表。它是位長度為len的有符號整數。len是在測試用例中定義的,因此您可以簡單地使用它而不必重新定義它。雖然位字串 bit str 可能必須短於len,但應進行符號擴充套件。如果輸入位字串是空字串,則新的sinteger物件應該是乙個全零的列表。請注意,列表中儲存的所有位物...