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-hant/n/318219.html