一腹缩、類對象的生命周期
什么是類對象的生命周期?
就是從對象創(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) 默認當(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的伙伴可以多多交流昌跌。