目錄
Python如何管理記憶體" >Python如何管理記憶體
Python 中的引用循環" >Python 中的引用循環
Python 垃圾收集器 (gc)" >Python 垃圾收集器 (gc)
如何使用 gc 模块" >如何使用 gc 模块
使用 gc 调试垃圾收集" >使用 gc 调试垃圾收集
避免 Python 内存管理中的陷阱" >避免 Python 内存管理中的陷阱
注意对象范围" >注意对象范围
使用 weakref避免引用循环" >使用 weakref避免引用循环
手動中斷參考循環" >手動中斷參考循環
首頁 後端開發 Python教學 Python 記憶體管理的工作原理,你了解嗎?

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

Apr 12, 2023 pm 04:25 PM
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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

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

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1319
25
PHP教程
1269
29
C# 教程
1248
24
PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

在PHP和Python之間進行選擇:指南 在PHP和Python之間進行選擇:指南 Apr 18, 2025 am 12:24 AM

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

sublime怎麼運行代碼python sublime怎麼運行代碼python Apr 16, 2025 am 08:48 AM

在 Sublime Text 中運行 Python 代碼,需先安裝 Python 插件,再創建 .py 文件並編寫代碼,最後按 Ctrl B 運行代碼,輸出會在控制台中顯示。

PHP和Python:深入了解他們的歷史 PHP和Python:深入了解他們的歷史 Apr 18, 2025 am 12:25 AM

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Golang vs. Python:性能和可伸縮性 Golang vs. Python:性能和可伸縮性 Apr 19, 2025 am 12:18 AM

Golang在性能和可擴展性方面優於Python。 1)Golang的編譯型特性和高效並發模型使其在高並發場景下表現出色。 2)Python作為解釋型語言,執行速度較慢,但通過工具如Cython可優化性能。

vscode在哪寫代碼 vscode在哪寫代碼 Apr 15, 2025 pm 09:54 PM

在 Visual Studio Code(VSCode)中編寫代碼簡單易行,只需安裝 VSCode、創建項目、選擇語言、創建文件、編寫代碼、保存並運行即可。 VSCode 的優點包括跨平台、免費開源、強大功能、擴展豐富,以及輕量快速。

notepad 怎麼運行python notepad 怎麼運行python Apr 16, 2025 pm 07:33 PM

在 Notepad 中運行 Python 代碼需要安裝 Python 可執行文件和 NppExec 插件。安裝 Python 並為其添加 PATH 後,在 NppExec 插件中配置命令為“python”、參數為“{CURRENT_DIRECTORY}{FILE_NAME}”,即可在 Notepad 中通過快捷鍵“F6”運行 Python 代碼。

See all articles