點評:下面的程序對實際開發并沒有什么意義,但卻是CPython中的一個大坑,這道題旨在考察面試者對官方的Python解釋器到底了解到什么程度。
a, b, c, d = 1, 1, 1000, 1000 print(a is b, c is d) def foo(): e = 1000 f = 1000 print(e is f, e is d) g = 1 print(g is a) foo()
結果: True False True False True
上面代碼中 a is b的結果是True但c is d的結果是False,這一點的確讓人費解。這個結果是因為CPython出于性能優化的考慮,把頻繁使用的整數對象用一個叫small_ints的對象池緩存起來造成的。
small_ints緩存的整數值被設定為[-5, 256]這個區間,也就是說,如果使用CPython解釋器,在任何引用這些整數的地方,都不需要重新創建int對象,而是直接引用緩存池中的對象。
如果整數不在該范圍內,那么即便兩個整數的值相同,它們也是不同的對象。
CPython底層為了進一步提升性能還做了一個設定:對于同一個代碼塊中值不在small_ints緩存范圍之內的整數,如果同一個代碼塊中已經存在一個值與其相同的整數對象,那么就直接引用該對象,否則創建新的int對象。
需要大家注意的是,這條規則對數值型適用,但對字符串則需要考慮字符串的長度,這一點可以自行證明。
擴展:如果你用PyPy(另一種Python解釋器實現,支持JIT,對CPython的缺點進行了改良,在性能上優于CPython,但對三方庫的支持略差)來運行上面的代碼,你會發現所有的輸出都是True。