非原創(chuàng)掠哥,如侵,請告知
原文來自git : https://github.com/leisurelicht/wtfpython-cn
下面是一個在互聯(lián)網(wǎng)上非常有名的例子.
>>> a = 256
>>> b = 256
>>> a is b
True
>>> a = 257
>>> b = 257
>>> a is b
False
>>> a = 257; b = 257
>>> a is b
True
說明:
is
和 ==
的區(qū)別
is
運算符檢查兩個運算對象是否引用自同一對象 (即, 它檢查兩個運算對象是否相同).==
運算符比較兩個運算對象的值是否相等.因此
is
代表引用相同,==
代表值相等. 下面的例子可以很好的說明這點,
>>> [] == []
True
>>> [] is [] # 這兩個空列表位于不同的內(nèi)存地址.
False
256
是一個已經(jīng)存在的對象, 而 257
不是
當(dāng)你啟動Python 的時候, 數(shù)值為 -5
到 256
的對象就已經(jīng)被分配好了. 這些數(shù)字因為經(jīng)常被使用, 所以會被提前準(zhǔn)備好.
Python 通過這種創(chuàng)建小整數(shù)池的方式來避免小整數(shù)頻繁的申請和銷毀內(nèi)存空間.
引用自 https://docs.python.org/3/c-api/long.html
當(dāng)前的實現(xiàn)為-5到256之間的所有整數(shù)保留一個整數(shù)對象數(shù)組, 當(dāng)你創(chuàng)建了一個該范圍內(nèi)的整數(shù)時, 你只需要返回現(xiàn)有對象的引用. 所以改變1的值是有可能的. 我懷疑這種行為在Python中是未定義行為. :-)
>>> id(256)
10922528
>>> a = 256
>>> b = 256
>>> id(a)
10922528
>>> id(b)
10922528
>>> id(257)
140084850247312
>>> x = 257
>>> y = 257
>>> id(x)
140084850247440
>>> id(y)
140084850247344
這里解釋器并沒有智能到能在執(zhí)行 y = 257
時意識到我們已經(jīng)創(chuàng)建了一個整數(shù) 257
, 所以它在內(nèi)存中又新建了另一個對象.
當(dāng) a
和 b
在同一行中使用相同的值初始化時球拦,會指向同一個對象.
>>> a, b = 257, 257
>>> id(a)
140640774013296
>>> id(b)
140640774013296
>>> a = 257
>>> b = 257
>>> id(a)
140640774013392
>>> id(b)
140640774013488
當(dāng) a 和 b 在同一行中被設(shè)置為
257
時, Python 解釋器會創(chuàng)建一個新對象, 然后同時引用第二個變量. 如果你在不同的行上進(jìn)行, 它就不會 "知道" 已經(jīng)存在一個257
對象了.這是一種特別為交互式環(huán)境做的編譯器優(yōu)化. 當(dāng)你在實時解釋器中輸入兩行的時候, 他們會單獨編譯, 因此也會單獨進(jìn)行優(yōu)化. 如果你在
.py
文件中嘗試這個例子, 則不會看到相同的行為, 因為文件是一次性編譯的.