2017-01-06 60 views
2

我明白的是,在CPython的2.x和3.x,一些整數是單身:意外引用計數

>>> a = 256; a is 256 # or any integer from -5 to 256 
True 

>>> a = 257; a is 257 # or any other integer outside the magic range 
False 

因此,如果我在範圍內的整數運行sys.getrefcount -5 256,我發現了很多我的導入包都引用了整數:由於其自己參考參數

>>> sys.getrefcount(1) 
1470 

我也明白,sys.getrefcount返回1比你想的那樣,:

>>> a = 257; sys.getrefcount(a) 
2 

什麼我不明白的是:

>>> sys.getrefcount(257) 
3 

爲什麼3,而不是2?我能理解,我可能會在自己的範圍內(計數1)已經創建了一個臨時變量,並明確sys.getrefcount會增加其自身的另一個參考(計數2),但哪裏第三個從哪裏來,爲什麼沒有在前面的例子中發生?更重要的是:是否還有其他可能出現的情況,導致可能對輸出產生誤解?

以上所有的都是複製的,我在64位的Python 2.7.12和3.5.1由蟒蛇,在OSX上運行,並且還對32位的Python 2.7.5分佈在Windows上運行。但是,在較舊的Python版本(Windows上的32位Python 2.5.4)上,sys.getrefcount(257)返回2,這對我來說更爲期望。

+0

重要嗎?實現細節可能會或可能不會導致將不變的文字作爲常量進行緩存。 –

+0

從文檔中,*返回對象的引用計數。返回的計數通常比您預期的要高,因爲它包含(臨時)引用作爲getrefcount()的參數。* –

+0

@HunterMcMillen:這只是3個引用中的2個,OP注意到他們已經設法計算遠。 –

回答

3

您正在運行到一個實現細節在這裏。編譯器通常可以緩存不可改變文字值:

>>> import dis 
>>> compile("sys.getrefcount(257)", '', 'single').co_consts 
(257, None) 
>>> dis.dis(compile("sys.getrefcount(257)", '', 'single')) 
    1   0 LOAD_NAME    0 (sys) 
       2 LOAD_ATTR    1 (getrefcount) 
       4 LOAD_CONST    0 (257) 
       6 CALL_FUNCTION   1 
       8 PRINT_EXPR 
      10 LOAD_CONST    1 (None) 
      12 RETURN_VALUE 

'single'是通過交互式解釋所使用的模式)。

我們在這裏看到3所引用;一個從co_consts元組代碼對象,一個堆棧(從LOAD_CONST指令)上,和一個用於sys.getrefcount()方法本身。

+0

謝謝。所以我認爲我們可以相信,在任何其他情況下(可能更重要的情況),'sys.getrefcount'不會神祕地碰到引用計數(通過* more *比預期的1)*? – jez

+0

@jez:你可以信任'sys.getrefcount()'。您可以隨時[創建Python的調試版本](https://hg.python.org/cpython/file/3.6/Misc/SpecialBuilds.txt),讓您更詳細地跟蹤引用計數,如果您有理由相信是某處的錯誤。 –