簡體   English   中英

為什么不同數據類型的地址不同[Python]?

[英]Why the addresses of different datatypes different [Python]?

>>> 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

>>> 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如何將地址分配給各種數據類型,特別是字符串。

根據計算機的體系結構,數據類型將以不同的字節長度存儲在內存中。 例如,字符串中的每個ASCII字符都需要一個字節來存儲它,而整數可以以任意位數存儲,最大長度取決於所存儲數字的大小。 我不太確定,但是python可能還會在已分配內存的不同區域中存儲不同的數據類型。

Python還在分配的內存中存儲的不僅僅是您為其提供的變量。 IDE也在該區域中運行。 因此,在兩次分配之間可能已經存儲了一些其他變量。

對於更新#1,看看這個

id恰好是CPython中的地址,是實現的詳細信息; 僅保證它們對於同時存在的對象是不同的。

您觀察到的分組是因為CPython預創建了許多對象,包括-5256以及TrueFalse 通常情況下,這些值不會出現在其他任何地址,這是可能的,因為它們是不可變的類型。

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

可以使用ctypes來訪問您熟悉的C類型,但是這樣做通常很麻煩且冒險。 例如,如果將Python字符串傳遞給更改C字符串的函數,則會破壞字符串本身。 Python期望字符串是不可變的,並且可以共享它們並緩存其哈希。

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

其次,您應該意識到Python中的所有東西都是對象。 在C語言中,當您執行c[0] ,您正在從一系列存儲位置中請求第一個值。 在Python中,不一定是這種情況。 對於標准列表,它由數組支持,但是其地址對您隱藏。 您看到的是通過id()獲得的對象的地址。 在這種情況下, c是一個字符串,但是c[0]也是如此(Python中沒有字符類型)。 這意味着當您要求c[0] ,Python會創建一個新字符串來表示您請求的字符(或更確切地說,子字符串)。 幸運的是,Python並不是每次都會自動創建一個新字符串,因為Python會自動自動插入1個字符的字符串。

另外,請記住,Python對象具有結構並且也會消耗內存。 關於C的最好的事情之一是可以很好地控制內存布局,但是您在Python中失去了這一方面。 不利的一面是,您不必手動分配和釋放內存,這是一種緩解(我進行了大量C和Python編程,所以我看到了好處)。

第三,是一個很大的內存分配和Python中釋放發生。 根據Python的構建方式以及用於分配內存的底層操作系統策略,可能發生多種情況,導致地址沒有順序增加。 但是由於所有事物都是對象,因此所有事物都會發生基礎分配。

我有這個疑問,是因為我首先學習了C ++(老實說,是Turbo C ++),而Python中定義字符串地址的方式與C ++中的情況大不相同。 我猜這在Python中還可以,因為我們無法通過Python中的對象地址訪問對象,對嗎?

是的,沒有。 當您說c[0] ,正在內部運行一種特殊的方法來從字符串中檢索子字符串。 這與您在C ++中獲得的不同。 但是,Python確實將字符串有效地存儲為字節序列。 因此,僅因為您看不到效率檢查的地址,並不意味着它不存在。 同樣,如上所述, c[0]返回一個新字符串,該字符串表示您想要的子字符串。 Python在這里很聰明,它將返回一個1個字符的字符串,但是它將是一個intern'd字符串。 您會看到一些字母具有相同的地址:

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

您會看到"o"的字符串共享相同的地址-順便說一句,示例是Python 2,但Python 3中存在相同的質量。

而且您是對的,您不能通過對象的地址訪問該對象-至少這不是語言的功能。 如何生成id是一個實現細節,但是您應該依靠每個Python解釋器都這樣做。

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

我在上面解釋了這一點,但要回顧一下: cc[0]c[0]中的不同。在Python中,第一個是字符串,第二個是請求包含字符串第一個字符的子字符串。

Python確實在許多領域中使用了競技場風格的內存管理方案,但是在大多數情況下,您不需要關心這一點。 如果您好奇,建議您看一下Python源代碼 Python子目錄具有許多語言和低級運行時支持位。 並且也意識到Python也預緩存了一些東西,這也可以解釋您在上面看到的地址中的差異。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM