Python提供的sys模塊中,有一個getsizeof()函數可以返回對象的佔用位元組數。
一、數據類型的佔用位元組數
Python支持的內置數據類型,包括int、float、bool、list、tuple、dict等等。但是它們各自所佔用的位元組數是不同的,通過getsizeof()函數可以輸出它們的實際佔用位元組數:
import sys i = 5 f = 3.1415926 b = False l = [1, 2, 3] t = (4, 5, 6) d = {1: 'one', 2: 'two', 3: 'three'} print(sys.getsizeof(i)) # 28 print(sys.getsizeof(f)) # 24 print(sys.getsizeof(b)) # 24 print(sys.getsizeof(l)) # 64 print(sys.getsizeof(t)) # 48 print(sys.getsizeof(d)) # 240
從輸出結果中可以看出,Python中int類型佔用28個位元組,float和bool類型佔用24個位元組,list類型佔用64個位元組,tuple類型佔用48個位元組,dict類型佔用240個位元組。
二、變數佔用位元組數
除了數據類型,變數本身也會佔用一定的位元組數。在Python中,變數實際上是一個指向對象內存地址的指針。因此,即使是一個空的變數,也會佔用一定的內存。下面的代碼演示了一些變數在佔用內存時的一些差異:
import sys a = 5 b = 'hello' c = [1, 2, 3] d = {'one': 1, 'two': 2, 'three': 3} e = [] f = () print(sys.getsizeof(a)) # 28 print(sys.getsizeof(b)) # 62 print(sys.getsizeof(c)) # 88 print(sys.getsizeof(d)) # 240 print(sys.getsizeof(e)) # 56 print(sys.getsizeof(f)) # 48
可以看到,int類型的變數佔用28個位元組,字元串類型的變數佔用62個位元組,list類型的變數佔用88個位元組,dict類型的變數佔用240個位元組。同時,即使是一個空的list和tuple,也分別佔用了56和48個位元組。
三、垃圾回收機制
Python中的垃圾回收機制對於內存的使用也有一定的影響。在Python中,除了引用計數,還有一種垃圾回收機制叫做循環垃圾回收機制。當一個對象沒有被引用時,垃圾回收器會將其清理掉。但是當一個對象被刪除時,它所包含的子對象不一定會被立即清理。
以下代碼演示了一個示例。當刪除一個對象時,它所包含的子對象不一定會被立即清理,需要等到垃圾回收器運作時才能清理:
import sys import gc class A(object): def __init__(self): self.b = B(self) class B(object): def __init__(self, a): self.a = a a = A() print(sys.getsizeof(a)) # 48 a = None gc.collect()
在上面的示例中,A實例中包含一個B實例,而B實例又包含一個指向A實例的引用。當刪除A實例時,它所包含的B實例並不會立即被清理。只有在運行垃圾回收器時,才會清理掉這個B實例。因此,在實際應用中,需要格外注意循環引用的情況。
四、位元組碼編譯
Python中的位元組碼編譯也會對內存使用產生影響。對於一個函數來說,它的位元組碼不僅要佔用一部分內存,而且每次調用函數時,都需要重新編譯一次函數的位元組碼。
以下代碼演示了位元組碼編譯對內存使用的影響:
import sys def test(): i = 5 j = 10 k = 15 return i + j + k print(sys.getsizeof(test)) # 136
上面的代碼演示了一個簡單的函數,內部只創建了3個變數。不過,即使這個函數很短,它的位元組碼編譯佔用了136個位元組。
五、內存分配、釋放和復用
Python中的內存分配、釋放和復用機制也會對內存使用產生影響。對於比較小的對象,Python會採用內存池機制進行分配和釋放,以避免頻繁的調用操作系統的內存分配和釋放函數。同時,在一些情況下,Python也會採用內存復用機制進行優化,從而避免不必要的內存分配。
以下代碼演示了Python的內存池和內存復用機制:
import sys a = 1000 b = 1000 print(id(a)) # 139933595660672 print(id(b)) # 139933595660672 print(sys.getsizeof(a)) # 28 c = [1, 2, 3] d = [1, 2, 3] print(id(c)) # 139933596098880 print(id(d)) # 139933595632320 print(sys.getsizeof(c)) # 64
上面的代碼演示了兩個示例。在第一個示例中,Python對於比較小的int數據類型採用了內存復用機制,因此,變數a和b的內存地址是一樣的,並且它們所佔用的位元組數也很小。而在第二個示例中,list類型的數據較大,因此Python並沒有採用內存復用機制,變數c和d的內存地址不一樣,並且它們所佔用的位元組數也較大。
原創文章,作者:QAWPG,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/318219.html