美文网首页
Python类对象的生命周期与内存管理机制

Python类对象的生命周期与内存管理机制

作者: 摸着石头过河_崖边树 | 来源:发表于2020-03-27 22:32 被阅读0次

一、类对象的生命周期

什么是类对象的生命周期?
就是从对象创建 ----> 对象使用 ----> 对象销毁
废话少说,我们直接上代码来看

class Person(object):
   # 1.可以拦截对象的创建
   def __new__(cls, *args, **kwargs):
        print('__new__方法调用')
       return super(Person, cls).__new__(cls, *args, **kwargs)

   # 2.创建对象完成后会自动调用这个方法,并把实例传递给init方法
    def __init__(self):
       print('__init__初始化方法')
       self.name = 'zb'

   # 3.对象释放的时候自动调用
   def __del__(self):
       print('__del__对象释放')
 
  p = Person()  # 创建对象
  del p      # 删除对象

结果输出

__new__方法调用
__init__初始化方法
 __del__对象释放

由此可见
创建对象时候先后调用new --> init
删除对象的时候 调用del

二、内存管理机制:

介绍内存管理之前我们先熟悉几个函数,之后我们会用到

 print(id(p))   # 打印内存地址 10进制
 print(hex(id(p)))  # 打印内存地址 16进制
 print(sys.getrefcount(p))  #查看对象的引用计数器的值

python 是万物皆对象,所有基本数据类型都是对象,但是常用数据类型的对象地址相同

 num1 = 2
 num2 = 2
 print(hex(id(num1)), hex(id(num2)))
 结果:0x1097fd070     0x1097fd070

内存管理包括2个机制并存引用计数器机制(性能高) + 垃圾回收机制(性能低,但是能解决循环引用问题)

2.1 引用计数器:计算对象被引用的次数是+1 取消引用-1

 import sys
class Person(object):
      pass
 p1 = Person()  # 引用计数器 = 1
 print(sys.getrefcount(p1))

 p2 = p1      # 引用计数器 = 2
 print(sys.getrefcount(p1))

 del p1    # 引用计数器 = 1

 del p2    # 引用计数器 = 1
 
//  结果:2
         3

注意:sys.getrefcount(p1)函数会自动将p1的引用计数器+ 1, 所以计算的时候要-1 引用计数 0 表示对象会被销毁

2.1.1 引用计数器+1 4个场景
A. 创建对象的时候 + 1; p = Person();
B . 对象赋值的时候 + 1; p2 = p
C. 对象作为函数的参数 + 2; func(p) 函数里面有2个引用
D. 对象作为某个对象的容器对象 + 1 ; a = [p]

2.1.2 引用计数器-1 4个场景
A. 对象被删除 -1; del p
B. 对象被重新赋值 -1; p = 123
C. 函数执行完毕,离开作用域-1;
D. 针对对象的容器对象的销毁 -1; del a

2.2 垃圾回收机制
引用计数机制虽然可以管理内存,但是不能解决循环引用问题,于是引用垃圾回收机制

  objgraph.count('Person')   # 查看类对象引用个数

垃圾回收机制底层原理

  # 1、收集所有的"容器对象"(列表、字典、元祖、自定义对象),通过双向链表(集合)进行引用
  # 2、针对每一个"容器对象",通过一个变量gc_refs来记录当前的引用计数器
  # 3、对象每个'容器对象',找到他引用的'容器对象',并将这个'容器对象'的引用计数器 -1
  # 4、经过步骤3之后,如果一个'容器对象'的引用计数器未0 就代表这个东西可以被回收啦,肯定是循环引用导致的

垃圾回收机制底层优化:分代回收 (优化垃圾回收性能)

垃圾检测触发机制:垃圾回收器 新增的对象个数 - 消亡的对象 达到一定的阈值才会触发垃圾回收

   # 阈值设置
  import gc
  print(gc.get_threshold())
   # (700, 10, 10)  默认当阈值大于700 检测一次   大于10 1代检测   大于10 2代加测
  # 设置垃圾检测
  gc.set_threshold(1000, 5, 5)

2.2.1 垃圾回收触发时机
A. 自动触发 : 先开启机制 后设置阈值

 import gc
# 判断是否开启垃圾回收
isenable = gc.isenabled()
if isenable == False:
      # 1. 开启回收
      gc.enable() 
#设置阈值
gc.set_threshold(500, 10, 10)

B.手动触发 : 解决循环引用

import objgraph   # 引用计数器count
import gc         # 垃圾回收机制
import weakref    # 弱引用
class Person(object):
    def __del__(self):   // 实现了del 不能自动回收
          print('Person对象被释放啦')

class Dog(object):
      def __del__(self):
          print('Dog对象被释放啦')

p = Person()
d = Dog()
# 循环引用
p.pet = d
d.master = p
 # d.master = weakref.ref(p)  #解决循环引用方式一 弱引用的应用
# p.pet = None     # 解决循环引用方式二 指向None
del p
del d
# 解决循环引用方式三 垃圾回收机制手动回收
# gc.collect(1)
print(objgraph.count('Person'))
print(objgraph.count('Dog'))

总结

解决循环引用方案 :

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

最后赠言

学无止境,学习Python的伙伴可以多多交流。

相关文章

  • Python类对象的生命周期与内存管理机制

    一、类对象的生命周期 什么是类对象的生命周期?就是从对象创建 ----> 对象使用 ----> 对象销毁废话少说...

  • Android优化-内存优化总结篇

    一、Android内存管理机制 1、Java对象的生命周期 Java对象的生命周期经历7个阶段,分别是创建阶段、应...

  • iOS 内存管理机制

    iOS内存管理机制原理 iOS内存管理机制的原理是引用计数,引用计数是一个简单而有效的管理对象生命周期的方式。当这...

  • Android内存管理机制

    Android内存管理机制的定义 内存的分配 内存的回收 管理机制的说明 管理的内存对象 进程 对象 变量 管理的...

  • python内存管理机制

    Python内存管理机制 Python内存管理机制主要包括以下三个方面: 引用计数机制 垃圾回收机制 内存池机制 ...

  • python复习

    1.Python的内存管理机制:Python中一切皆对象,每一个Python对象的核心都是一个结构体,它的内部有一...

  • iOS 是如何管理内存的?

    Objective-C内存管理机制 Objective-C中的对象都是基于引用计数来管理生命周期的。简单来说就是,...

  • Python内存管理机制

    转载: Python内存管理机制 c/c++中:通过malloc和free进行内存的申请和释放 python/ja...

  • Android内存如何泄露

    Android内存如何泄露 对象的生命周期溢出 对象无限创建引起内存爆满 生命周期溢出 内存泄露说到底是,对象的生...

  • 无标题文章

    简述OC中内存管理机制 管理机制:是使用一种叫做引用计数的机制来管理内存中的对象.OC中每个对象都对应着自己的引用...

网友评论

      本文标题:Python类对象的生命周期与内存管理机制

      本文链接:https://www.haomeiwen.com/subject/mslfuhtx.html