博客
关于我
python 垃圾回收机制
阅读量:180 次
发布时间:2019-02-28

本文共 1849 字,大约阅读时间需要 6 分钟。

引用计数器与垃圾回收机制

在Python编程中,引用计数器和垃圾回收机制是内存管理的核心部分。这些机制帮助开发者避免内存泄漏,同时确保程序能够高效运行。本文将详细讲解引用计数器及其在垃圾回收中的作用。


引用计数器的基本概念

引用计数器记录了一个对象被引用的次数。当引用次数为零时,对象将被垃圾回收系统销毁。通过sys.getrefcount()方法可以获取对象的引用次数。需要注意的是,该方法返回的引用次数会包含一个临时引用(因为函数本身会持有一个引用),所以实际引用次数应减1。

例如:

import sysclass Uranus:    passu1 = Uranus()print(sys.getrefcount(u1) - 1)  # 输出: 1

引用计数变化的场景分析

引用计数会在以下场景中发生变化:

  • 对象创建

    • 创建对象时,引用计数自动增加1。
  • 对象引用

    • 当一个对象被另一个对象引用时,引用计数增加1。
  • 对象作为函数参数传入

    • 当对象作为函数参数传入时,函数和调用函数的上下文都会持有引用,引用计数增加2。
  • 对象存储在容器中

    • 当对象存储在列表、字典或其他容器中时,容器持有引用,引用计数增加1。
  • 例如:

    import sysclass Uranus:    passu1 = Uranus()u2 = u1def func(obj):    print(sys.getrefcount(obj) - 1)func(u1)

    执行上述代码,输出将为:

    2

    循环引用的问题

    循环引用是内存泄漏的常见原因之一。当两个对象互相引用时,引用计数无法归零,导致对象无法被回收。

    为了检测循环引用,可以使用objgraph模块:

    import objgraphclass Person:    passclass Animal:    passP = Person()A = Animal()print(objgraph.count("Person"))  # 输出: 0print(objgraph.count("Animal"))  # 输出: 0P.pet = AA.master = Pprint(objgraph.count("Person"))  # 输出: 1print(objgraph.count("Animal"))  # 输出: 1del Pdel Aprint(objgraph.count("Person"))  # 输出: 1print(objgraph.count("Animal"))  # 输出: 1

    尽管删除了PA,由于循环引用,引用计数无法归零,导致内存泄漏。


    垃圾回收机制

    Python默认采用分代回收算法,结合引用计数器和循环引用检测机制,自动管理内存。

    垃圾回收阈值

    垃圾回收的触发条件是基于内存使用率和阈值。可以使用gc.get_threshold()查看当前阈值:

    import gcprint(gc.get_threshold())  # 输出: (700, 10, 10)

    阈值由三个参数决定:默认值为700, 10, 10


    分代回收

    分代回收通过将对象分为代来管理,减少频繁扫描的开销。每次垃圾回收时,先清理一代对象,如果无法清理,则移动至下一代,直到清理完成。

    可以手动设置分代阈值:

    gc.set_threshold(100, 5, 5)

    垃圾回收的控制

    垃圾回收默认开启,可以通过gc.disable()关闭,gc.enable()重新启用,gc.isenabled()检查状态。

    gc.disable()gc.enable()gc.isenabled()  # 输出: True

    如何手动触发垃圾回收

    可以通过gc.collect()手动触发垃圾回收。

    gc.collect()

    如何避免循环引用

    为了避免循环引用,可以使用弱引用模块weakref

    import weakrefP = Person()A = Animal()weak_ref = weakref.ref(P)A.master = weak_ref

    弱引用不会增加引用计数,可以安全地管理循环引用。

    此外,可以通过手动释放引用来减少计数:

    A.master = None

    结论

    引用计数器和垃圾回收机制是Python内存管理的核心。通过合理使用引用计数,可以避免内存泄漏。对于复杂项目,循环引用检测和处理至关重要。掌握这些概念,能够显著提升代码的性能和稳定性。

    转载地址:http://agqc.baihongyu.com/

    你可能感兴趣的文章
    PostgreSQL学习总结(8)—— PostgreSQL 基于数据库和基于模式(schema)的多租户分析
    查看>>
    PostgreSQL学习总结(9)—— PostgreSQL 运算符与表达式
    查看>>
    PostGreSql学习笔记001---PostgreSQL10.4安装(Windows)_支持PostGreGis_PostJDBC
    查看>>
    PostGreSql学习笔记002---Navicat Premium中管理PostGreSql 错误:字段rolcatupdate 不存在
    查看>>
    PostgreSQL学习笔记:PostgreSQL vs MySQL
    查看>>
    PostgreSQL实现shape数据转geojson数据(地图工具篇.18)
    查看>>
    PostgreSQL导入shape数据(地图工具篇.10)
    查看>>
    PostGreSql工作笔记003---在Navicat中创建数据库时报错rolcatupdate不存在_具体原因看其他博文_这里使用pgAdmin4创建管理postgre
    查看>>
    PostGreSql工作笔记004---PostGreSql修改密码_windows和linux下修改
    查看>>
    Postgresql常用命令行操作_以及Navicat操作PostGis时的问题_自动截取长度_WKB structure does not match exp---PostgreSQL工作笔记005
    查看>>
    PostgreSQL忘记密码
    查看>>
    PostgreSQL数据库pg_dump命令行不输入密码的方法
    查看>>
    PostgreSQL新手入门
    查看>>
    postgresql树状结构查询示例
    查看>>
    PostgreSQL流复制参数max_wal_senders详解
    查看>>
    postgresql流复制配置
    查看>>
    PostgreSQL清空表并保留表结构、清空数据库还原数据库为新建时的状态的方法
    查看>>
    PostgreSQL的 initdb 源代码分析之九
    查看>>
    PostgreSQL的安装与使用指南
    查看>>
    postman之参数化详解
    查看>>