逐行解釋和整體解釋的理解
首先跟著筆者的思路讀以下的代碼
片段<一>
>>> a = 10.1
>>> b = 10.1
>>> a is b
False
返回false說明a和b不是指向了同一個對象,可以查看id進行判斷
>>> id(a)
140475784803760
>>> id(b)
140475784803736
片段<二>
接著看以下這一段的代碼
>>> (10.1) is (10.1)
True
>>> def foo():
... a = 10.1
... b = 10.1
... return a is b
...
>>> foo()
True
片段<三>
趣者可以嘗試著用的CPython環境裏執行下面的代碼:
def foo():
a = 10.1
b = 10.1
return a is b
print(foo())
而結果總是True。
片段<四>
In [45]: def demo1():
...: return 10.2
...:
In [46]: def demo2():
...: return 10.2
...:
In [47]:
In [47]: print(demo1() is demo2())
False
In [48]:
而結果總是False。
《幫助理解文檔介紹》
背景知識
CPython的代碼的“編譯單元”是函數——每個函數單獨編譯,得到的結果是一個PyFunctionObject對象,其中帶有字節碼、常量池等各種信息。Python的頂層代碼也被看作一個函數。函數之間有嵌套時,外層函數的代碼並不包含內層函數的代碼,而只是包含創建出內層函數的函數對象(PyFunctionObject)的邏輯。(這裏的編譯單元跟之前提到過的代碼塊可以理解為同一個概念--"都是編譯時的基本單位")
在同一個編譯單元(PyFunctionObject)裏出現的值相同的常量,只會在常量池裏出現一份,一定會對應到運行時的同一個對象。所以在foo()的例子裏,a和b都從同一個常量池項獲取值;
在不同的編譯單元裏,值相同的常量不一定
代碼幫助理解:
In [48]: a = 255
In [49]: def demo():
...: b = 255
...: c = 255
...: print(a is b)
...: print(b is c)
...:
In [50]: demo()
True
True
In [51]:
註:255為小整數對象池之內的數 所以 不同的編譯單元 執行的結果為true
In [51]: a = 257
In [52]: def demo():
...: b = 257
...: c = 257
...: print(a is b)
...: print(b is c)
...:
In [53]: demo()
False
True
In [54]:
註:257不是小整數對象池範圍的的數據 a和b 為兩個編譯單元所以結果為false 這裏可以觀察到 在同一個編譯單元裏 同樣的整數(b和c)只會創建一份所以返回True
“逐行解釋”?
其實在CPython的交互式解釋器(例如python命令不指定參數時)裏,每輸入一行可以立即執行的代碼,Python解釋器就會把一行當作一個編譯單元來編譯到字節碼並解釋執行;如果輸入的代碼尚未構成一個完整的單元,例如函數聲明或者類聲明,則等到獲得了完整單元的輸入後再當作一個編譯單元來處理。
所以當我們在CPython的交互式解釋器中分別輸入"a = 10.1"、"b = 10.1"這兩行時,它們分別被當作一個編譯單元處理,其中的常量池沒有共享,常量池項也都是各自新創建的,所以會得到a is b為False的結果。
而在同一環境裏輸入"(10.1) is (10.1)"時,這一行被看作一個編譯單元,其中兩次對10.1這個常量的使用都變成了對同一對象的引用,因而is的結果為True。
例:
In [57]: 10.1 is 10.1
Out[57]: True
當把 一下代碼放到同一個py文件裏去執行的時候 兩行代碼就會處於同一個編譯單元中,a is b就會是True。 同一個代碼塊(編譯單元)共享同一個常量池
a = 10.1
b = 10.1
print(a is b)
>>>True
逐行解釋和整體解釋的理解