深入解析sys.getsizeof()

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

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
QAWPG的頭像QAWPG
上一篇 2025-01-11 16:28
下一篇 2025-01-11 16:28

相關推薦

  • Python中import sys的作用

    Python是一種非常強大的編程語言,它的標準庫提供了許多有用的模塊和函數。sys模塊是Python標準庫中的一個重要模塊,用於與Python解釋器和操作系統進行交互。它允許開發者…

    編程 2025-04-28
  • 深入解析Vue3 defineExpose

    Vue 3在開發過程中引入了新的API `defineExpose`。在以前的版本中,我們經常使用 `$attrs` 和` $listeners` 實現父組件與子組件之間的通信,但…

    編程 2025-04-25
  • 深入理解byte轉int

    一、字節與比特 在討論byte轉int之前,我們需要了解字節和比特的概念。字節是計算機存儲單位的一種,通常表示8個比特(bit),即1字節=8比特。比特是計算機中最小的數據單位,是…

    編程 2025-04-25
  • 深入理解Flutter StreamBuilder

    一、什麼是Flutter StreamBuilder? Flutter StreamBuilder是Flutter框架中的一個內置小部件,它可以監測數據流(Stream)中數據的變…

    編程 2025-04-25
  • 深入探討OpenCV版本

    OpenCV是一個用於計算機視覺應用程序的開源庫。它是由英特爾公司創建的,現已由Willow Garage管理。OpenCV旨在提供一個易於使用的計算機視覺和機器學習基礎架構,以實…

    編程 2025-04-25
  • 深入了解scala-maven-plugin

    一、簡介 Scala-maven-plugin 是一個創造和管理 Scala 項目的maven插件,它可以自動生成基本項目結構、依賴配置、Scala文件等。使用它可以使我們專註於代…

    編程 2025-04-25
  • 深入了解LaTeX的腳註(latexfootnote)

    一、基本介紹 LaTeX作為一種排版軟件,具有各種各樣的功能,其中腳註(footnote)是一個十分重要的功能之一。在LaTeX中,腳註是用命令latexfootnote來實現的。…

    編程 2025-04-25
  • 深入理解Python字符串r

    一、r字符串的基本概念 r字符串(raw字符串)是指在Python中,以字母r為前綴的字符串。r字符串中的反斜杠(\)不會被轉義,而是被當作普通字符處理,這使得r字符串可以非常方便…

    編程 2025-04-25
  • 深入了解Python包

    一、包的概念 Python中一個程序就是一個模塊,而一個模塊可以引入另一個模塊,這樣就形成了包。包就是有多個模塊組成的一個大模塊,也可以看做是一個文件夾。包可以有效地組織代碼和數據…

    編程 2025-04-25
  • 深入探討馮諾依曼原理

    一、原理概述 馮諾依曼原理,又稱“存儲程序控制原理”,是指計算機的程序和數據都存儲在同一個存儲器中,並且通過一個統一的總線來傳輸數據。這個原理的提出,是計算機科學發展中的重大進展,…

    編程 2025-04-25

發表回復

登錄後才能評論