python面试题02:内存管理机制之前言及小整数池和大整数池的概念

前言

这节是接前言的python面试题01 is与==的区别来接着深入引入的,但是,这一小节不会写太多,后续有时间我会继续更新。在面试中,如果面试官没有向我们提问 你是否有了解过python的内存管理机制,能简单说说这类的问题的话,我们可以在回答is和 == 的区别时进行加深引入,来向面试官展现下自己的知识储备。
ps:当然这个对平时的开发没有啥太大的影响,毕竟到内存优化这一步了,那应该使用C++、C等其他语言。这作为学习是非常好的。如果本节内容有不实的地方,请指正!

python的内存管理机制-对象创建

这个标题不太好写,我们在了解python的内存优化机制之前,应该先明白一句话:“在python中一切皆对象”, 如果还不理解可以看下这篇文章 《 彻底搞懂Python一切皆对象!!!》,我觉得讲得还可以,简单来说,** 无论是list, str, int, tuple, set, dict 这些类型说白了,都是继承于Object这个基类的**
因为python的底层其实是C写的,到现在是python+C混合的模式,但是,底层依旧是C,所以我们从官网下载python的C源码,可以在其源码的include目录下的object.h文件中看到下面的代码:
在这里插入图片描述
在这里插入图片描述
这段源码中,可以看到注释中写着指向python对象的底层其实都会转为PyObejcr这个结构体,而这个结构体至少拥有四个属性,分别是 上一个对象, 下一个对象 、类型、引用个数。
另外,有多个元素组成的对象则是使用PyVarObject,其中里面的属性就有 PyObject结构体中上一个对象、下一个对象、类型、引用个数等和 Ob_size里的items=元素,元素个数.
所以知道这个概念后我们可以再了解下环状双向链表refchain,python所有创建的对象都会存入这个环状双向链表中,这里,我们仅仅作为了解,后需在讲python的GC机制时,便会继续介绍。

小整数池和大整数池的区别

小整数池:是指 [-5, 257) 这个区间的数,python为了优化内存,在我们启动python编译器时,便会将这个区间的数字全部创建,并保存在内存中,这些对象便称为小整数池,后续我们再创建这些数字的时候,都不需要再取申请内存空间,而是直接引用小整数池里的对象,节省了频繁申请内存的成本,总之一句话:小整数池[-5,257)这个区间的数字,会在运行程序之初就全部创建好了
大整数池:是指不属于 [-5, 257) 这个区间的数,在我们运行代码过程中,每创建一个大整数都会被python加载到大整数池中,在同次运行中,下一次再创建,便会引用之前已经创建好的对象,即使我们将之前创建好的对象全部del, 开辟的这块内存都不会被回收,直到程序运行结束,总之一句话: ** 大整数池是在我们运行程序的过程中,每创建一个新整数都会加入到大整数池中,后续再创建相同的整数就进行复用即可,直到程序结束,大整数池才会被销毁 **
ps: 大整数池和小整数池都是存放在同一个数组指针里面的,也就是free_list里面,在python运行之初就会自动创建一个257+5=262大小的数组,随后不在这个区间的数会自动增加到这个数组里面,直至程序结束。

例子说明

小整数池例子,这里采用的是命令行终端运行,注意终端 shell 运行和直接运行整个py文件时不一样的,观察下面的例子,你就会明白了

>>> a = 1
>>> b = 1
>>> id(a) == id(b)
True
>>> a = 257
>>> b = 257
>>> id(a) == id(b)
False

上面的例子很好的说明了小整数池的概念,在python运行之初便会自动创建了,但是,好像不符合大整数池的概念,但是当我们将上述代码写入py文件中,运行整个文件又会不一样。

a = 257
b = 257
print(id(a) == id(b))   # 运行结果为True

这是直接运行整个py文件的,会造成这样的原因主要在于使用python shell的时侯每次运行,大整数池都会重新创建,而使用py文件则会将增个代码加入内存中,一起运行。
通过上面的例子已经充分理解了大小整数池的概念,接下来可以运行下面的例子再试试看,可以用大小整数池的概念理解下。

c1 = 1000
c2 = 1000

print("c1 is c2 ", c1 is c2)

class C1:
    a = 100
    b = 100
    c = 1000
    d = 1000


class C2:
    a = 100
    b = 1000

print("C1.a is C1.b ", C1.a is C1.b)
print("C1.c is C1.d ", C1.c is C1.d)
print("C1.a is C2.a ", C1.a is C2.a)
print("C1.c is C1.d ", C1.c is C1.d)

class D:
    def __init__(self):
        self.a = 1000
        self.b = 1000

D1 = D()
D2 = D()

print("D1.a is D1.b", D1.a is D1.b)
print("D1.a is D2.a", D1.a is D2.a)
print("D1.a is c1", D1.a is c1)

总结

大小整数池其实是基于python内存管理机制的free_list,其他类型也有相应的free_list, 所谓的大小整数池是为了更好的理解,python 在整数这一块,优化策略不过是维护好其free_list,只不过这个free_list初始值包括了[-5, 257)这个左闭右开的区间的数,也就是小整数池,后续在创建大整数时,就往这个free_list不断添加新的数。
在这里向各位推荐个博客https://wklken.me/,这里讲的可比我好太多了,在写这些的时候,我虽然理解了一些,但还是会去搜一些文章,以此补全自己的不足,望大佬指正,共同进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌~晓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值