Python培训
400-996-5531
整数,在Python中,不是以传统的2、4或8字节实现,而是将其实现为以230为基数的整数数组,因此Python支持超长整数。又因为整数没有明确的长度限制,所以在Python中使用整数非常方便,即使我们对很长的整数进行运算,也不必担心整数溢出。但这种便利的代价是资源分配较高,同时常用运算(例如加法,乘法,除法)的执行效率较低。
Python中的每个整数都实现为一个C语言结构体, 如下所示。
可以观察到,与其它的较长整数相比,-5至256范围内的较小整数使用非常频繁,为了性能上优势,Python在初始化过程中预先分配了该范围内的整数对象,并使它们成为单例,因此每次在使用较小整数时, 使用的是相应单例的引用,而不是重新分配新的整数对象。
下面是Python官方文档中关于整数预分配的相关内容:
“当前的整数实现会为-5至256之间的所有整数维护一个整数对象数组,当你创建该范围内的整数时, 你实际得到的是现有整数对象的引用。”
在CPython的源码中,可以在IS_SMALL_INT宏和longobject.c模块中的get_small_int函数中跟踪此优化。因此,Python为常用整数节省了大量的空间和计算量。
验证这些较小整数对象是否是单例
对于CPython, 内置的id函数返回对象的内存地址。这意味着,如果较小整数确实是单例,对于相同较小整数值的两个实例, id函数应该返回相同的内存地址,而对于较长整数的多个实例应返回不同的内存地址,这确实是我们观察到的:
较小整数的这种单例现象也可以在计算过程中观察到。在下面的示例中,通过对三个不同的整数2、4和10进行两次运算,我们得到了相同的目标值6,并且在这两种情况下,我们看到id函数返回了相同的内存地址:
验证这些较小整数对象是否经常被引用
我们已经确定,在Python中使用较小整数,是通过引用它们相应的单例对象来实现,而无需每次都重新分配内存创建整数对象。现在我们需要验证以下假设:“Python初始化的时候, 通过这些单例对象,确实节省了大量的内存分配操作”;我们可以通过检查每个整数值的引用计数来验证上面的假设。
引用计数
引用计数,维护着同一对象在不同位置被引用的数目,对象每次被引用时,其属性ob_refcnt(对象引用计数)会增加1,对象引用被取消时, ob_refcnt会减少1,当引用计数为0时,该对象将会被垃圾回收。
我们使用sys模块中的getrefcount函数来获取一个对象的当前引用计数;较小整数的引用计数很高,表明使用率很高,同时引用计数随着这些整数值的增加而降低;这证实了, 在Python初始化期间, 相比于较长整数,较小整数被更多对象引用。
整数值0被引用的最多——359次,沿着分布图的长尾,可以看到引用计数的峰值为2的幂次,如32, 64, 128和256。Python在初始化的过程中本身需要较小整数值,因此通过单例模式节省了大约1993次的较小整数对象的创建。
这些引用计数是在新打开的Python进程计算的,这意味着,Python初始化时,需要使用一些整数值进行计算,并通过使用较小整数值的单例来加速计算。
在通常的编程实践中, 相比于较长整数,较小整数的使用更频繁,并且这些整数值的单例实例可以为Python节省大量的计算量和内存分配操作。
达内每年输送10万+人才,18年来帮助80万学员高薪就业;协助16万家企业解决人才需求。拥有完善的就业保障体系,116万家招聘雇主合作企业。每天产生数千个招聘岗位,提供更多就业机会给到达内学员。找Python培训,选达内就对了!
版权声明:转载文章来自公开网络,版权归作者本人所有,推送文章除非无法确认,我们都会注明作者和来源。如果出处有误或侵犯到原作者权益,请与我们联系删除或授权事宜。
填写下面表单即可预约申请免费试听! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!
Copyright © 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有
Tedu.cn All Rights Reserved