Python類對象的生命周期與內(nèi)存管理機制

一、類對象的生命周期

什么是類對象的生命周期?
就是從對象創(chuàng)建 ----> 對象使用 ----> 對象銷毀
廢話少說,我們直接上代碼來看

class Person(object):
   # 1.可以攔截對象的創(chuàng)建
   def __new__(cls, *args, **kwargs):
        print('__new__方法調(diào)用')
       return super(Person, cls).__new__(cls, *args, **kwargs)

   # 2.創(chuàng)建對象完成后會自動調(diào)用這個方法,并把實例傳遞給init方法
    def __init__(self):
       print('__init__初始化方法')
       self.name = 'zb'

   # 3.對象釋放的時候自動調(diào)用
   def __del__(self):
       print('__del__對象釋放')
 
  p = Person()  # 創(chuàng)建對象
  del p      # 刪除對象

結(jié)果輸出

__new__方法調(diào)用
__init__初始化方法
 __del__對象釋放

由此可見
創(chuàng)建對象時候先后調(diào)用new --> init
刪除對象的時候 調(diào)用del

二、內(nèi)存管理機制:

介紹內(nèi)存管理之前我們先熟悉幾個函數(shù),之后我們會用到

 print(id(p))   # 打印內(nèi)存地址 10進制
 print(hex(id(p)))  # 打印內(nèi)存地址 16進制
 print(sys.getrefcount(p))  #查看對象的引用計數(shù)器的值

python 是萬物皆對象,所有基本數(shù)據(jù)類型都是對象,但是常用數(shù)據(jù)類型的對象地址相同

 num1 = 2
 num2 = 2
 print(hex(id(num1)), hex(id(num2)))
 結(jié)果:0x1097fd070     0x1097fd070

內(nèi)存管理包括2個機制并存引用計數(shù)器機制(性能高) + 垃圾回收機制(性能低,但是能解決循環(huán)引用問題)

2.1 引用計數(shù)器:計算對象被引用的次數(shù)是+1 取消引用-1

 import sys
class Person(object):
      pass
 p1 = Person()  # 引用計數(shù)器 = 1
 print(sys.getrefcount(p1))

 p2 = p1      # 引用計數(shù)器 = 2
 print(sys.getrefcount(p1))

 del p1    # 引用計數(shù)器 = 1

 del p2    # 引用計數(shù)器 = 1
 
//  結(jié)果:2
         3

注意:sys.getrefcount(p1)函數(shù)會自動將p1的引用計數(shù)器+ 1, 所以計算的時候要-1 引用計數(shù) 0 表示對象會被銷毀

2.1.1 引用計數(shù)器+1 4個場景
A. 創(chuàng)建對象的時候 + 1; p = Person();
B . 對象賦值的時候 + 1; p2 = p
C. 對象作為函數(shù)的參數(shù) + 2; func(p) 函數(shù)里面有2個引用
D. 對象作為某個對象的容器對象 + 1 ; a = [p]

2.1.2 引用計數(shù)器-1 4個場景
A. 對象被刪除 -1; del p
B. 對象被重新賦值 -1; p = 123
C. 函數(shù)執(zhí)行完畢,離開作用域-1;
D. 針對對象的容器對象的銷毀 -1; del a

2.2 垃圾回收機制
引用計數(shù)機制雖然可以管理內(nèi)存,但是不能解決循環(huán)引用問題,于是引用垃圾回收機制

  objgraph.count('Person')   # 查看類對象引用個數(shù)

垃圾回收機制底層原理

  # 1、收集所有的"容器對象"(列表、字典、元祖、自定義對象),通過雙向鏈表(集合)進行引用
  # 2、針對每一個"容器對象",通過一個變量gc_refs來記錄當(dāng)前的引用計數(shù)器
  # 3、對象每個'容器對象',找到他引用的'容器對象',并將這個'容器對象'的引用計數(shù)器 -1
  # 4、經(jīng)過步驟3之后,如果一個'容器對象'的引用計數(shù)器未0 就代表這個東西可以被回收啦,肯定是循環(huán)引用導(dǎo)致的

垃圾回收機制底層優(yōu)化:分代回收 (優(yōu)化垃圾回收性能)

垃圾檢測觸發(fā)機制:垃圾回收器 新增的對象個數(shù) - 消亡的對象 達到一定的閾值才會觸發(fā)垃圾回收

   # 閾值設(shè)置
  import gc
  print(gc.get_threshold())
   # (700, 10, 10)  默認(rèn)當(dāng)閾值大于700 檢測一次   大于10 1代檢測   大于10 2代加測
  # 設(shè)置垃圾檢測
  gc.set_threshold(1000, 5, 5)

2.2.1 垃圾回收觸發(fā)時機
A. 自動觸發(fā) : 先開啟機制 后設(shè)置閾值

 import gc
# 判斷是否開啟垃圾回收
isenable = gc.isenabled()
if isenable == False:
      # 1. 開啟回收
      gc.enable() 
#設(shè)置閾值
gc.set_threshold(500, 10, 10)

B.手動觸發(fā) : 解決循環(huán)引用

import objgraph   # 引用計數(shù)器count
import gc         # 垃圾回收機制
import weakref    # 弱引用
class Person(object):
    def __del__(self):   // 實現(xiàn)了del 不能自動回收
          print('Person對象被釋放啦')

class Dog(object):
      def __del__(self):
          print('Dog對象被釋放啦')

p = Person()
d = Dog()
# 循環(huán)引用
p.pet = d
d.master = p
 # d.master = weakref.ref(p)  #解決循環(huán)引用方式一 弱引用的應(yīng)用
# p.pet = None     # 解決循環(huán)引用方式二 指向None
del p
del d
# 解決循環(huán)引用方式三 垃圾回收機制手動回收
# gc.collect(1)
print(objgraph.count('Person'))
print(objgraph.count('Dog'))

總結(jié)

解決循環(huán)引用方案 :

1、weakref 弱引用 - 一個對象的弱引用 一對多的引用用需要弱引用字典
2、指向None 置空對象
3、 gc.collect(1) 垃圾回收機制回收

最后贈言

學(xué)無止境,學(xué)習(xí)Python的伙伴可以多多交流。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 生命周期的概念:世界上的萬事萬物都有它的生命周期,那么針對對象的生命周期到底是從哪里開始從哪里結(jié)束呢?當(dāng)我們創(chuàng)建一...
    hello_我的哥閱讀 7,872評論 0 5
  • python內(nèi)存管理是通過引用計數(shù)來實現(xiàn)的。當(dāng)對象的引用計數(shù)為0時,會被gc回收。 為了探索對象在內(nèi)存的存儲,我們...
    冬季戀歌1218閱讀 1,797評論 0 2
  • 1.元類 1.1.1類也是對象 在大多數(shù)編程語言中,類就是一組用來描述如何生成一個對象的代碼段。在Python中這...
    TENG書閱讀 1,427評論 0 3
  • [TOC] 內(nèi)存管理 一、托管堆基礎(chǔ) 在面向?qū)ο笾校總€類型代表一種可使用的資源,要使用該資源,必須為代表資源的類...
    _秦同學(xué)_閱讀 4,129評論 0 3
  • 我還是長大了。 我還是只能把你留下來。 我們彼此相似,我們彼此又不同。 我走你走過的路,卻會選擇一種你也許沒有嘗試...
    lemo_8b6a閱讀 303評論 1 0

友情鏈接更多精彩內(nèi)容