Python面向对象之对象生命周期篇

Python对象生命周期

生命周期:一个对象,从诞生到消亡的过程。当一个对象被创建时,会在内存中分配相应的内存空间进行存储。当这个对象不在使用时,为了节约内存,就会把这个对象释放

监听对象的生命过程

# __new__方法:当我我们创建一个对象的时候,用于给这个对象分配内存的方法
# 通过拦截这个方法,可以修改对象的创建过程,例如单例模式
#  __init__方法:相当于构造函数,创建时自动调用
# __del__方法,相当于析构函数,自动调用

小案例如下:

"""
实现功能:记录Person类产生了多少个实例,有多少个
"""
class Person:
    __count = 0
    def __init__():
        Person.__count += 1
        pass
    def __del__(self):
        Person.__count -= 1
        pass
    @classmethod
    def log(cls):
        print("count:%d" %cls.count)
        pass
    pass

Python是如何掌握一个对象的生命?

内存管理机制

# python会根据不同的类型以及内容,开辟不同的空间大小进行存储,返回该空间的地址给外界接收(称为“引用”),用于后续对这个对象的操作
# 可通过id()函数获取内存地址(10进制)
# 通过hex函数查看对应的16位地址
# 对于整数和短小的字符,Python会进行缓存,不会创建多个对象
num1 = 2
num2 = 2
print(id(num1))
print(id(num2))
# 这里num1  num2的地址是一样的
# 容器对象,存储其他对象,仅仅时其他对象对象的引用,而不是其他对象本身

对象内存关系图如下:

请添加图片描述

垃圾回收机制

  • 引用计算器:一个对象,会记录这自身被引用的个数,增加一个引用,加一,减少一个引用,减一,当引用个数为0时,系统会自动回收掉该内存,查看方式如下:

    import sys
    sys.getrefcount(ZhangSan) # 注意:使用这种方法时,会增加一次引用,所以到时候必须减一
    # +1的场景:对象被创建   对象被引用(P1 = P2)对象被作为参数,传入到一个函数中(会+2)  对象作为一个元素,存储再容器中
    # -1的场景:对象被del  对象的引用被赋予其他值(p1 = 123)  一个对象离开它的作用域(一个函数执行完毕时 或 内部的局部变量关联的对象,它的引用会被自动取消) 对象所在的容器被销毁,或从容器中删除对象
    
    • 循环引用问题:图示如下:其中我们可以发现,这两个对象存在了互相引用的关系,但如果我del掉这两个对象,这两个对象并不会释放内存,就会存在内存被无效占用的情况,这是十分可惜的

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hw02zJ4l-1640334304946)(python面向对象生命周期.assets/1640331091300.png)]

      import objgraph
      # 这里是一个新加入的包,包通过setting中的project 中的第一选项,中的➕进行添加
      # objgraph.count("类名") 可以查看,垃圾回收机制中对象的引用次数 跟踪对象的个数
      # 内存管理机制 = 引用计算器机制 + 垃圾回收机制
      

      垃圾回收机制

      # 主要作用:从经历过“引用计数器机制”依然未被释放的对象中,找到“循环引用”,干掉相关对象
      # 底层机制(了解):
      # 1.收集所有的“容器对象”(可以引用其他对象的对象,基础类型不算),通过一个双向链表进行引用
      # 2.针对每一个“容器对象”,通过一个变量gc_refs来记录当前对应的引用计数
      # 3.对于每个“容器对象”,找到它引用的“容器对象”,并将这个“容器对象”的引用计数 -1
      # 4.经过步骤3之后,如果一个“容器对象”的引用计数为0,就代表可以被回收了,肯定是“循环引用”
      # 但如果每次都把所有对象检查一边,就会很浪费性能,所以python采用了一个名为“分代回收”机制(思想)
      # 1.首先默认一个对象被创建出来以后,属于0代
      # 2.如果经历这一代“垃圾回收”后,依然存活,则划分到下一代
      # 3.“垃圾回收”的周期顺序为:0代”垃圾回收“达到一定次数,会触发 0代和1代回收 1代"垃圾回收"达到一定次数,会触发0代,1代和2代回收
      # 再垃圾回收器中,新增的对象个数- 消亡的对象个数,达到一定的阈值时,才会触发垃圾检测
      # 查看和设置相关参数
      import gc
      print(gc.get_threshold())
      gc.set_threshold(70,10,5)  # 相差700时开始检测,10  5 触发一代和二代 
      # 自动回收
      # 1.开启垃圾回收机制
      gc.enable() # 开启垃圾回收机制(默认开启)
      gc.disable() # 关闭垃圾回收机制
      gc.isenabled() # 判定是否开启
      # 手动回收:
      import gc
      gc.collect()  # 运行回收垃圾
      
      # 阈值:
      gc.get_threshold() # 获取自动自动回收阈值
      gc.set_threshold() # 设置自动回收阈值
      # 版本兼容问题:
      # python 3.x版本如上
      # python 2.x版本:一旦有一个对象实现了del方法,系统便不会自动帮我们释放
      # 解决方案1:尽量避免循环应用
      # 解决方案2:采用软引用(即计算器不会加1),例如:
      import weakref
      import 
      p.pet = d                           # d的引用次数为2,但删除p以后,d会减一
      gc.set_threshold(70,10,5)
      p.pet = {"dog":weakref(d1),"cat":weakref(c1)}
      # 当像上面那样引用对象较多时,可以采用字典
      # weakref。WeakValueDictionary({"dog": d1,"cat": c1})
      
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值