2017-08-26 92 views
-1
>>> a=5 
>>> b=6 
>>> id(a) 
10914496 
>>> id(b) 
10914528 
>>> c='Hello' 
>>> d='World' 
>>> id(c) 
139973573252184 
>>> id(d) 
139973616356744 
>>> e=(4>5) 
>>> f=(4<5) 
>>> id(e) 
10739968 
>>> id(f) 
10740000 
  1. 爲什麼string和boolean/int數據類型的地址長度如此不同?
  2. 爲什麼隨後的聲明在地址上有相當大的不同,與數據類型的大小相比?

更新#1爲什麼不同數據類型的地址不同[Python]?

>>> id(c) 
139973616356856 
>>> id(c[0]) 
139973652926112 
>>> id(c[1]) 
139973653190728 
>>> id(c[2]) 
139973653634272 
>>> id(c[3]) 
139973653302104 

我有這個疑問,因爲我學過C++第一(說實話,用Turbo C++)和字符串的地址都是用Python定義方式是什麼很大的不同發生在C++中。我想這在Python中是好的,因爲我們不能通過它在Python中的地址來訪問對象,對嗎?

此外,c和c [0]具有不同的地址有什麼意義?對於某些人來說,這些問題可能是不必要的,但我很好奇,不知道Python如何爲各種數據類型(特別是字符串)分配地址。

+0

另外解釋downvote,因爲這是我在這個網站上的第一個問題。 –

回答

1

首先,我們應該從Python開始,它的工作方式與C不同。在C中,數組只是一塊內存。在Python中,它是一個對象。 cc[0]id()與結果不一樣。

其次,你應該認識到Python中的每一件事都是一個對象。在C中,當你想做類似c[0]的事情時,你正在請求一系列內存位置的第一個值。在Python中,情況並非一定如此。對於一個標準列表,它由一個數組支持,但是它的地址對你來說是隱藏的。你看到的是通過id()對象的地址。在這種情況下,c是一個字符串,但這樣是c[0](沒有字符類型在Python)。這意味着當您要求c[0]時,Python正在創建一個新字符串來表示您請求的字符(或者說,子字符串)。幸運的是,Python實際上並沒有每次創建一個新的字符串,因爲Python會自動實現一個字符的字符串。

另外,記住,Python對象有一個結構和太消耗內存。關於C的最好的事情之一是能夠非常控制內存佈局,但是你在Python中失去了這方面的能力。翻蓋面是,你不必做手工分配和內存,這是一種解脫(我做了很多C和Python編程,讓我看到了好處)釋放。

三,很多更多的內存分配和釋放在Python中發生。根據構建Python的方式以及分配內存的底層操作系統策略,可能會發生任何數量的事情,導致地址不會按順序增加。但由於一切是一個對象,有一個潛在的分配正在發生的一切。

我有這個疑問,因爲我學過C++第一(說實話,用Turbo C++)和字符串的地址都是用Python定義方式是用C會發生什麼++非常不同。我想這在Python中是好的,因爲我們不能通過它在Python中的地址來訪問對象,對嗎?

yes和no。當你說c[0]時,在引擎蓋下面正在運行一個特殊的方法來從字符串中檢索子字符串。這與你在C++中獲得的不同。但是,Python確實將字符串作爲字節序列進行有效存儲。所以只是因爲你看不到效率檢查地址,並不意味着它不在那裏。另外,正如我上面提到的,c[0]返回一個新的字符串,表示您想要的子字符串。 Python在這裏很聰明,會返回一個1個字符的字符串,但它將是一個內部字符串。你可以看到一些字母具有相同的地址:

>>> for c in "hobo": 
...  print c, id(c) 
... 
h 4434994600 
o 4434861432 
b 4434859712 
o 4434861432 

你可以看到,"o"共享相同的地址字符串 - 順便說一句,這個例子的Python 2,但在Python 3

存在同樣的質量

而且你是正確的,你不能訪問由它的地址對象 - 至少這是不是語言的一個特徵。如何生成ids是一個實現細節,但是你應該指望每個Python解釋器都這樣做。

另外,爲c和c [0]設置不同的地址有什麼意義?對於某些人來說,這些問題可能是不必要的,但我很好奇,不知道Python如何爲各種數據類型(特別是字符串)分配地址。

我解釋這上面,而是概括:cc[0]比在C.在Python不同,首先是字符串和第二請求包含字符串的第一個字符的子字符串。

Python做在許多領域使用的舞臺風格的內存管理方案,但在大多數情況下,你不需要關心這個。如果你好奇,我建議你看看Python source codePython子目錄具有許多語言和低級運行時支持位。同時也意識到,Python也預先緩存了一些內容,這也可以解釋上述地址中的差異。

2

根據您的計算機架構,數據類型將以不同的字節長度存儲在內存中。例如,一個字符串中的每個ASCII字符需要一個字節來存儲它,而整數可以以任何位長度存儲,直至達到極限,這取決於所存儲數字的大小。我不完全確定,但python可能會在分配的內存的不同區域中存儲不同的數據類型。

Python在分配的內存中存儲的內容不僅僅是你給它的變量。 IDE也在該領域運行。因此,在兩個分配之間可能存儲了其他一些變量。

對於更新#1,看看this

+0

我明白你的觀點。謝謝。也請看看我的更新#1。 –

1

id恰好是在地址CPython的是一個實現細節;它們只能保證與同時存在的對象不同。

您觀察到的分組是因爲CPython預先創建了一些對象,包括-5256以及TrueFalse。在一般情況下,這些值不會出現在任何其他地址上,因爲它們是不可變的類型,所以可以做到這一點。

第二個問題,關於字符串中的切片,是因爲Python的字符串對象不相互引用。沒有字符類型,因此從字符串中提取字符會生成新的字符串。同樣,其中一些可能被緩存(實際字符串)。字符串對象的地址不一定是其內容的地址。

您可以使用​​來訪問您熟悉的C類型,但這樣做通常很尷尬且有風險。例如,如果你將一個Python字符串傳遞給一個改變一個C字符串的函數,那麼你會破壞字符串本身; Python期望字符串是不可變的,並且可以共享它們並緩存它們的哈希值。

相關問題