程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python筆記,面向對象(12)內存管理機制

編輯:Python

內存管理機制

  • 存儲方面
  • 垃圾回收方面
    • 引用計數器
      • 概念
      • 查看引用計數
      • 舉例
        • 引用計數的兩個場景
        • 循環引用問題
    • 垃圾回收
      • 主要作用
      • 底層機制
        • 怎樣找到“循環引用”?
        • 如歌提升查找“循環引用”的性能?
        • 查看以及修改機制配置參數
      • 垃圾回收時機
        • 自動回收
        • 手動回收

存儲方面

1.在Python中萬物接對象

  • 不存在基本數據類型
  • 0,1.2,True,False,“abc”這些全都是對象

2.所有對象中,都會在內存中開辟一塊空間進行存儲

  • 會根據不同的類型及其內容,開辟不同的空間大小進行存儲
  • 返回該空間的地址給外界接受(稱為"引用"),用於後續對這個對象的操作
    • 可通過id()函數獲取內存地址(10進制)
    • 通過hex()函數可以查看對應的16進制地址
class Person:
pass
p = Person
print(p)
print(id(p))
print(hex(id(p)))
#結果
<class '__main__.Person'>
2495730068704
0x245151aace0
  • 3.對於整數和短小的字符,Python會進行緩存,不會創建對個相同對象
num1 = 2
num2 = 2
print(id(num1), id(num2))
#結果
1632086026576 1632086026576

4.容器對象,存儲的其他對象,僅僅是其他對象的引用,並不是其他對象本身

垃圾回收方面

引用計數器

概念

  • 一個對象,會記錄著自身被引用的個數
  • 每增加一個引用,這個對象的引用計數會自動+1
  • 每減少一個引用,這個對象的引用計數會自動-1

查看引用計數

  • import sys
  • sys.getrefcount: 注意會大一(調用這個函數,會被當做一個參數傳遞給這個函數)
import sys
class Person:
pass
p1 = Person()
print(sys.getrefcount(p1))
p2 = p1
print(sys.getrefcount(p1))
del p2
print(sys.getrefcount(p1))
del p1
#結果
2
3
2

舉例

引用計數的兩個場景

  • 引用計數+1場景
    • 對象被創建:p1 = Person()
    • 對象被引用:p1 = p2
    • 對象被作為參數,傳入到一個函數中
    • 對象作為一個元素,存儲在容器中:i = [P1]
  • 引用計數-1場景
    • 對象的別名被顯示銷毀:del p1
    • 對象的別名被賦予新的對象:p1 = 123
    • 一個對象剛離開他的作用域:一個函數執行完畢時,內部的局部變量關聯的對象,她的引用對象會再次被釋放
    • 對象的容器被銷毀,或從容器中刪除對象

循環引用問題

內存洩露:一個對象在內存中無法使用,沒有被釋放的情況就是內存洩露

#objgraph.count()可以查看,垃圾回收器,跟蹤的對象個數
import objgraph
class Person:
pass
class Dog:
pass
p = Person()
d = Dog()
print(objgraph.count("Person"))
print(objgraph.count("Dog"))
p.pet = d
d.master = p
#刪除p,d之後,對應的對象是否被釋放掉
del p
del d
print(objgraph.count("Person"))
print(objgraph.count("Dog"))
p.pet = d
d.master = p
del p
del d
#結果
1
1
1

垃圾回收

主要作用

從經歷過"引用計數器機制"仍未被釋放的對象中,找到"循環引用",干掉相關對象

底層機制

怎樣找到“循環引用”?

如歌提升查找“循環引用”的性能?

查看以及修改機制配置參數

import gc
print(gc.get_threshold()) #查看
gc.set_threshold(200, 5, 5) #更改
#結果
(700, 10, 10) 每查10次0代的,查一次1代的,依次類推

垃圾回收時機

自動回收

import gc
gc.disable()
print(gc.isenabled())
gc.enable()
print(gc.isenabled())
print(gc.get_threshold())
gc.set_threshold(1000, 5, 5) #一般往大調,提升性能,垃圾回收耗時間
##
False
True
(700, 10, 10)

手動回收

import objgraph
import gc
#定義兩個類
class Person:
pass
class Dog:
pass
#根據這兩個類,創建出兩個實例對象
p = Person()
d = Dog()
#讓兩個實例對象之間互相引用,造成循環引用
p.pet = d
d.master = p
#嘗試刪除可達到引用之後,測試真實對象是否有被回收
del p
del d
#通過"引用計數機制”無法回收,需要借助“垃圾回收機制”
gc.collect() #手動觸發回收,不管垃圾回收機制是否開啟,括號內寫幾就是回收哪一代
print(objgraph.count("Person"))
print(objgraph.count("Dog"))
#
0
0

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved