搜尋
首頁後端開發Python教學Python 記憶體管理的工作原理,你了解嗎?

Python 為開發者提供了許多便利,其中最大的便利之一是其幾乎無憂的記憶體管理。開發者無需手動為 Python 中的物件和資料結構分配、追蹤和釋放記憶體。運行時會為你完成所有這些工作,因此你可以專注於解決實際問題,而不是爭論機器級細節。

Python 記憶體管理的工作原理,你了解嗎?

儘管如此,即使是經驗不多的 Python 用戶,了解 Python 的垃圾收集和記憶體管理是如何運作的也是有好處的。了解這些機制將幫助你避免更複雜的專案可能出現的效能問題。你也可以使用 Python 的內建工具來監控程式的記憶體管理行為。

Python如何管理記憶體

每個 Python 物件都有一個引用計數,也稱為引用計數。 refcount 是持有對給定物件的引用的其他物件總數的計數。當你新增或刪除對物件的引用時,數字會上升或下降。當一個物件的參考計數變為零時,該物件將被釋放並釋放其記憶體。

什麼是參考?允許透過名稱或透過另一個物件中的存取器存取物件的任何內容。

這是一個簡單的例子:

x = "Hello there"

當我們向Python 發出這個命令時,引擎蓋下會發生兩件事:

  1. 該字串"Hello there"以Python 物件建立並儲存在記憶體中。
  2. 該名稱x在本地命名空間中建立並指向該對象,這會將其參考計數增加 1 到 1。

如果我們說y = x,那麼引用計數將再次提高到 2。

每當xandy超出範圍或從它們的命名空間中刪除時,對於每個名稱,字串的參考計數都會減少 1。一旦x和y都超出範圍或被刪除,字串的引用計數變為 0 並被刪除。

現在,假設我們創建了一個包含字串的列表,如下所示:

x = ["Hello there", 2, False]

字串保留在記憶體中,直到列表本身被刪除或包含字串的元素從列表中刪除。這些操作中的任何一個都將導致唯一持有對字串的參考的事物消失。

現在考慮這個範例:

x = "Hello there" y = [x]

如果我們從 中刪除第一個元素y,或完全刪除清單y,則字串仍在記憶體中。這是因為名稱x包含對它的引用。

Python 中的引用循環

在大多數情況下,引用計數工作正常。但有時你會遇到兩個物件各自持有對彼此的引用的情況。這稱為 參考週期。在這種情況下,物件的引用計數永遠不會達到零,也永遠不會從記憶體中刪除。

這是一個人為的例子:

x = SomeClass()
y = SomeOtherClass()
x.item = y
y.item = x

由於x並y持有彼此的引用,因此它們永遠不會從系統中刪除——即使沒有其他任何東西引用它們中的任何一個。

Python 自己的運行時為物件產生參考循環其實是相當普遍的。一個範例是帶有包含對異常本身的參考的回溯物件的異常。

在Python的早期版本中,這是一個問題。具有引用週期的物件可能會隨著時間的推移而累積,這對於長時間運行的應用程式來說是一個大問題。但 Python 此後引入了循環檢測和垃圾收集系統,用於管理引用循環。

Python 垃圾收集器 (gc)

Python 的垃圾收集器會偵測具有引用週期的物件。它透過追蹤作為「容器」的物件(例如列表、字典、自訂類別實例)並確定其中的哪些物件無法在其他任何地方存取來實現這一點。

一旦這些物件被挑選出來,垃圾收集器就會透過確保它們的參考計數可以安全地降為零來刪除它們。

絕大多數 Python 物件沒有引用週期,因此垃圾收集器不需要 24/7 運行。相反,垃圾收集器使用一些啟發式方法來減少運行頻率,並且每次都盡可能有效地運行。

當 Python 解釋器啟動時,它會追​​蹤已指派但未釋放的物件數量。絕大多數 Python 物件的生命週期都很短,因此它們會迅速出現和消失。但隨著時間的推移,更多長壽的物體會出現。一旦超過一定數量的此類物件堆積起來,垃圾收集器就會運作。

每次垃圾收集器運行時,它都會收集所有在收集中倖存下來的對象,並將它們放在一個稱為一代的群組中。這些「第一代」物件在參考週期中被掃描的頻率較低。任何在垃圾收集器中倖存下來的第一代物件最終都會遷移到第二代,在那裡它們被掃描得更少。

同样,垃圾收集器不会跟踪所有内容。例如,像用户创建的类这样的复杂对象总是被跟踪。但是不会跟踪仅包含简单对象(如整数和字符串)的字典,因为该特定字典中的任何对象都不会包含对其他对象的引用。不能保存对其他元素(如整数和字符串)的引用的简单对象永远不会被跟踪。

如何使用 gc 模块

通常,垃圾收集器不需要调整即可运行良好。Python 的开发团队选择了反映最常见现实世界场景的默认值。但是如果你确实需要调整垃圾收集的工作方式,你可以使用Python 的 gc 模块。该gc模块为垃圾收集器的行为提供编程接口,并提供对正在跟踪的对象的可见性。

gc当你确定不需要垃圾收集器时,你可以做的一件有用的事情是关闭它。例如,如果你有一个堆放大量对象的短运行脚本,则不需要垃圾收集器。脚本结束时,所有内容都将被清除。为此,你可以使用命令禁用垃圾收集器gc.disable()。稍后,你可以使用 重新启用它gc.enable()。

你还可以使用 手动运行收集周期gc.collect()。一个常见的应用是管理程序的性能密集型部分,该部分会生成许多临时对象。你可以在程序的该部分禁用垃圾收集,然后在最后手动运行收集并重新启用收集。

另一个有用的垃圾收集优化是gc.freeze(). 发出此命令时,垃圾收集器当前跟踪的所有内容都被“冻结”,或者被列为免于将来的收集扫描。这样,未来的扫描可以跳过这些对象。如果你有一个程序在启动之前导入库并设置大量内部状态,那么你可以gc.freeze()在所有工作完成后发出。这使垃圾收集器不必搜寻那些无论如何都不太可能被删除的东西。(如果你想对冻结的对象再次执行垃圾收集,请使用gc.unfreeze().)

使用 gc 调试垃圾收集

你还可以使用它gc来调试垃圾收集行为。如果你有过多的对象堆积在内存中并且没有被垃圾收集,你可以使用gc's 检查工具来找出可能持有对这些对象的引用的对象。

如果你想知道哪些对象持有对给定对象的引用,可以使用gc.get_referrers(obj)列出它们。你还可以使用gc.get_referents(obj)来查找给定对象引用的任何对象。

如果你不确定给定对象是否是垃圾收集的候选对象,gc.is_tracked(obj)请告诉你垃圾收集器是否跟踪该对象。如前所述,请记住垃圾收集器不会跟踪“原子”对象(例如整数)或仅包含原子对象的元素。

如果你想亲自查看正在收集哪些对象,可以使用 设置垃圾收集器的调试标志gc.set_debug(gc.DEBUG_LEAK|gc.DEBUG_STATS)。这会将有关垃圾收集的信息写入stderr。它将所有作为垃圾收集的对象保留在只读列表中。

避免 Python 内存管理中的陷阱

如前所述,如果你在某处仍有对它们的引用,则对象可能会堆积在内存中而不会被收集。这并不是 Python 垃圾收集本身的失败。垃圾收集器无法判断你是否不小心保留了对某物的引用。

让我们以一些防止对象永远不会被收集的指针作为结尾。

注意对象范围

如果你将对象 1 指定为对象 2 的属性(例如类),则对象 2 将需要超出范围,然后对象 1 才会:

obj1 = MyClass()
obj2.prop = obj1

更重要的是,如果这种情况发生在某种其他操作的副作用中,例如将对象 2 作为参数传递给对象 1 的构造函数,你可能不会意识到对象 1 持有一个引用:

obj1 = MyClass(obj2)

另一个例子:如果你将一个对象推入模块级列表并忘记该列表,则该对象将一直保留,直到从列表中删除,或者直到列表本身不再有任何引用。但是如果该列表是一个模块级对象,它可能会一直存在,直到程序终止。

简而言之,请注意你的对象可能被另一个看起来并不总是很明显的对象持有的方式。

使用 weakref避免引用循环

Python 的 weakref 模块允许你创建对其他对象的弱引用。弱引用不会增加对象的引用计数,因此只有弱引用的对象是垃圾回收的候选对象。

一个常见的用途weakref是对象缓存。你不希望仅仅因为它具有缓存条目而保留引用的对象,因此你将 aweakref用于缓存条目。

手動中斷參考循環

最後,如果你知道給定物件包含對另一個物件的引用,你總是可以手動中斷對該物件的參考。例如,如果你有instance_of_class.ref = other_object,你可以設定instance_of_class.ref = None何時準備刪除 instance_of_class。

透過了解 Python 記憶體管理的工作原理,我們對其垃圾收集系統如何幫助優化 Python 程式中的內存,以及如何使用標準庫和其他地方提供的模組來控制記憶體使用和垃圾收集。

原文標題:Python garbage collection and the gc module

以上是Python 記憶體管理的工作原理,你了解嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:51CTO.COM。如有侵權,請聯絡admin@php.cn刪除
Python和時間:充分利用您的學習時間Python和時間:充分利用您的學習時間Apr 14, 2025 am 12:02 AM

要在有限的時間內最大化學習Python的效率,可以使用Python的datetime、time和schedule模塊。 1.datetime模塊用於記錄和規劃學習時間。 2.time模塊幫助設置學習和休息時間。 3.schedule模塊自動化安排每週學習任務。

Python:遊戲,Guis等Python:遊戲,Guis等Apr 13, 2025 am 12:14 AM

Python在遊戲和GUI開發中表現出色。 1)遊戲開發使用Pygame,提供繪圖、音頻等功能,適合創建2D遊戲。 2)GUI開發可選擇Tkinter或PyQt,Tkinter簡單易用,PyQt功能豐富,適合專業開發。

Python vs.C:申請和用例Python vs.C:申請和用例Apr 12, 2025 am 12:01 AM

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。Python以简洁和强大的生态系统著称,C 则以高性能和底层控制能力闻名。

2小時的Python計劃:一種現實的方法2小時的Python計劃:一種現實的方法Apr 11, 2025 am 12:04 AM

2小時內可以學會Python的基本編程概念和技能。 1.學習變量和數據類型,2.掌握控制流(條件語句和循環),3.理解函數的定義和使用,4.通過簡單示例和代碼片段快速上手Python編程。

Python:探索其主要應用程序Python:探索其主要應用程序Apr 10, 2025 am 09:41 AM

Python在web開發、數據科學、機器學習、自動化和腳本編寫等領域有廣泛應用。 1)在web開發中,Django和Flask框架簡化了開發過程。 2)數據科學和機器學習領域,NumPy、Pandas、Scikit-learn和TensorFlow庫提供了強大支持。 3)自動化和腳本編寫方面,Python適用於自動化測試和系統管理等任務。

您可以在2小時內學到多少python?您可以在2小時內學到多少python?Apr 09, 2025 pm 04:33 PM

兩小時內可以學到Python的基礎知識。 1.學習變量和數據類型,2.掌握控制結構如if語句和循環,3.了解函數的定義和使用。這些將幫助你開始編寫簡單的Python程序。

如何在10小時內通過項目和問題驅動的方式教計算機小白編程基礎?如何在10小時內通過項目和問題驅動的方式教計算機小白編程基礎?Apr 02, 2025 am 07:18 AM

如何在10小時內教計算機小白編程基礎?如果你只有10個小時來教計算機小白一些編程知識,你會選擇教些什麼�...

如何在使用 Fiddler Everywhere 進行中間人讀取時避免被瀏覽器檢測到?如何在使用 Fiddler Everywhere 進行中間人讀取時避免被瀏覽器檢測到?Apr 02, 2025 am 07:15 AM

使用FiddlerEverywhere進行中間人讀取時如何避免被檢測到當你使用FiddlerEverywhere...

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具