Python内存管理

本文深入探讨了Python的内存管理机制,包括动态类型、引用计数、垃圾回收、缓冲池等。详细阐述了引用计数器原理、循环引用、垃圾回收的原则、gc机制、分代回收以及标记清除策略。同时介绍了整数对象缓冲池、字符串缓存和intern机制,展示了Python如何高效管理内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0. Python动态类型

  • 对象是存储在内存中的实体
  • 我们在程序中写的对象名,只是指向这一对象的引用(reference)
  • 引用和对象分离,是动态类型的核心
  • 引用可以随时指向一个新的对象(内存地址会不同)
    在这里插入图片描述

1. 引用计数机制

在Python中,每个对象都有存有指向该对象的引用总数,即引用计数(reference count)。

1.1 引用计数器原理

每个对象维护一个 ob_ref 字段,用来记录该对象当前被引用的次数 。

每当新的引用指向该对象时,它的引用计数ob_ref加1 。

每当该对象的引用失效时计数ob_ref减1 。

一旦对象的引用计数为0,该对象可以被回收,对象占用的内存空间将被释放。

它的缺点是需要额外的空间维护引用计数,这个问题是其次的 。最主要的问题是它不能解决对象的“循环引用”

循环引用见1.5

1.2 获取引用计数:getrefcount()

在这里插入图片描述

当使用某个引用作为参数,传递给getrefcount()时,参数实际上创建了一个临时的引用。因此,getrefcount()所得到的结果,会比期望的多1。

在这里插入图片描述

1.3 增加引用计数

当一个对象A被另一个对象B引用时,A的引用计数将增加1

在这里插入图片描述

1.4 减少引用计数

del删除或重新引用时,引用计数会变化(del只是删除引用)

在这里插入图片描述

1.5 循环引用的情况

x = [] 

y = [] 

x.append(y) 

y.append(x) 

在程序运行期间,应该被回收的内存并没有正确回收。这样的问题,属于内存泄漏。

1.6 引用计数机制的优缺点

  • 引用计数机制的优点:

    简单

    实时性

  • 引用计数机制的缺点:

    维护引用计数消耗资源

    循环引用时,无法回收

2. python垃圾回收

2.1 回收原则

当Python的某个对象的引用计数降为0时,可以被垃圾回收

2.2 gc机制

GC作为现代编程语言的自动内存管理机制,专注于两件事

  • 找到内存中无用的垃圾资源
  • 清除这些垃圾并把内存让出来给其他对象使用。

GC彻底把程序员从资源管理的重担中解放出来,让他们有更多的时间放在业务逻辑上。但这并不意味着码农就可以不去了解GC,毕竟多了解GC知识还是有利于我们写出更健壮的代码。

2.3 效率问题

垃圾回收时,Python不能进行其它的任务。频繁的垃圾回收将大大降低Python的工作效率。

当Python运行时,会记录其中分配对象(object allocation)和取消分配对象(object deallocation)的次数。当两者的差值高于某个阈值时,垃圾回收才会启动。

在这里插入图片描述

700:分配和取消分配次数相差的值

10,10:分带回收策略由这两个数字决定

2.4 三种情况触发垃圾回收

  • 调用gc.collect()
  • GC达到阀值时
  • 程序退出时

2.5 分代(generation)回收

这一策略的基本假设是:存活时间越久的对象,越不可能在后面的程序中变成垃圾。

  • Python将所有的对象分为0,1,2三代。

  • 所有的新建对象都是0代对象。

  • 当某一代对象经历过垃圾回收,依然存活,那么它就被归入下一代对象。

    0代对象被扫描10次之后还存活,就归为1代对象,以此类推。

    • 垃圾回收启动时,一定会扫描所有的0代对象。
    • 如果0代经过一定次数垃圾回收,那么就启动对0代和1代的扫描清理。
    • 当1代也经历了一定次数的垃圾回收后,那么会启动对0,1,2,即对所有对象进行扫描。

2.6 标记清除

标记-清除机制,顾名思义,首先标记对象(垃圾检测),然后清除垃圾(垃圾回收)。

主要用于解决循环引用

  1. 标记:活动(有被引用), 非活动(可被删除)

  2. 清除:清除所有非活动的对象

3. python缓冲池

3.1 整数对象缓冲池

对于[-5,256] 这样的小整数,系统已经初始化好,可以直接拿来用。

而对于其他的大整数,系统则提前申请了一块内存空间,等需要的时候在这上面创建大整数对象。

3.2 字符串缓存

为了检验两个引用指向同一个对象,我们可以用is关键字。is用于判断两个引用所指的对象是否相同。

当触发缓存机制时,只是创造了新的引用,而不是对象本身。

  • 注意: 这对于经常使用的数字和字符串来说也是一种优化的方案
  • 在这里插入图片描述

3.3 字符串的intern机制

python对于短小的,只含有字母数字的字符串自动触发缓存机制。其他情况不会缓存。

在这里插入图片描述

intern 主动触发缓存机制

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值