每一個編程語言的背后都有自己獨特的內存模型支持,比如最經典的C語言,一個int類型占8字節。那么在python中不區分數據類型,定義一個變量其在內存在占用多少字節呢?python中數據的運算其內存是如何變化的呢?
在回答上面的問題之前,首先看一下python中可變的數據和不可變數據
一、可變對象和不可變對象
Python一切數據皆為對象,python中的對象分成兩類:可變對象和不可變對象。所謂可變對象是指,對象的內容可變,而不可變對象是指對象內容不可變。
不可變(immutable):數值(int、float)、字符串(string)、元組(tuple)
可變(mutable):字典型(dictionary)、列表型(list)
根據對象的分類,可以將數據類型也做一個分類,可變數據類型與不可變數據類型:
可變數據類型:列表list和字典dict
不可變數據類型:整型int、浮點型float、字符串型string和元組tuple
這里的可變不可變,是指內存中的那塊內容是否可以被改變。
如果是不可變類型,在對對象本身操作的時候,必須在內存中新申請一塊區域(因為老區域不可變)。創建a=1整型對象,執行a=2時,內存中的對象1是不變的,只是重新創建了對象2。
如果是可變類型,對對象操作的時候,不需要再在其他地方申請內存,只需要在此對象后面連續申請(+/-)即可,也就是它的內存地址會保持不變,但區域會變長或者變短。
當對可變和不可變對象運算時會內存中會發生什么事情呢?對比來看
不可變數據類型:不允許變量的值發生變化,如果改變了變量的值,相當於是新建了一個對象,而對於相同的值的對象,在內存中則只有一個對象,內部會有一個引用計數來記錄有多少個變量引用這個對象;
可變數據類型:允許變量的值發生變化,即如果對變量進行append、+=等這種操作后,只是改變了變量的值,而不會新建一個對象,變量引用的對象的地址也不會變化,不過對於相同的值的不同對象,在內存中則會存在不同的對象,即每個對象都有自己的地址,相當於內存中對於同值的對象保存了多份,這里不存在引用計數,是實實在在的對象。
python對於數據的特殊處理
小整數
Python為了優化速度,避免為整數頻繁申請和銷毀內存空間,使用了小整數對象池。對小整數的定義是 [-5, 256] 這些整數對象是提前建立好的,不會被垃圾回收。在這個范圍內所有的整數都只會被建立一次。
a = 100 b = 100 print(id(a)) print(id(b)) ------------------------- 94125443429088 94125443429088
a = 200 b = 200 print a is b ----------------- True a = 300 b = 300 print a is b ----------------- False
大整數
大整數池: 只存儲包含標准字符(數字、字母、下划線)的字符串,不包含特殊字符的字符串 。
python為了避免創建大整數浪費的內存空間和時間,將創建過的大整數加入大整數池。
python中大整數池,默認大整數池里面為空,每一個py程序都有一個大整數池。使用大整數時如果大整數池里不存在該整數的話,會新建一個大整數對象。下次使用大整數時直接使用大整數池里的對象,而不是創建新的對象
py文件中,每次運行時都會將所有代碼加載到內存中,屬於一個整體,因此處於同一個代碼塊的大整數是同一個對象,所以兩者id是一樣的。
a = '12345' b = '12345' print id(a) print id(b) ----------------------------- 140139908067808 140139908067808 print a is b ----------------------------- True
其他數據類型
如果是其他普通類型對象的新建,python會請求內存,申請內存 。當n1的引用指向其他對象時,原有對象的引用計數會自動減1,沒有被引用的對象會立即回收。