详解Python小数据池和代码块缓存机制


Posted in Python onApril 07, 2021

前言

本文除"总结"外,其余均为认识过程;3.7.5;这部分官方文档不知道在哪里找,目前没有找到,有谁知道的可以麻烦留言吗? 谢谢了!

总结:

如果在同一代码块下,则采用同一代码块下的缓存机制;
如果是不同代码块,则采用小数据池的驻留机制;
需要注意的是,交互式输入时,每个命令都是一个代码块;

实现 Intern 保留机制的方式非常简单,就是通过维护一个字符串储蓄池,这个池子是一个字典结构,编译时,如果字符串已经存在于池子中就不再去创建新的字符串,直接返回之前创建好的字符串对象,
如果之前还没有加入到该池子中,则先构造一个字符串对象,并把这个对象加入到池子中去,方便下一次获取;

长度为0与1的字符串一定会被驻留;
字符串驻留发生在程序编译时;
被驻留的字符串必须由 ASCll 字母, 数字以及下划线组成;

1.代码块的缓存机制

Python 程序是由代码块构造的。块是一个 Python 程序的文本,它是作为一个单元执行的。
代码块:一个模块, 一个函数, 一个类, 一个文件等都是一个代码块;
交互方式:在 cmd 中进入 Python 解释器里面,输入的每一条命令都是一个代码块;

Python 在执行同一个代码块的初始化对象的命令时,会检查其值是否存在,如果存在,会将其重用;
满足代码块的缓存机制则它们在内存中只存在一个,即:id相同;
代码块的缓存机制的适用范围: int(float),str,bool;

int(float): 任何数字在同一代码块下都会复用;
bool: True 和 False 在字典中会以 1,0 方式存在,并且复用;
str:同一代码块中,值相同的字符串在内存中只存在一个:

s1 = 'janes@!#*ewq'
s2 = 'janes@!#*ewq'
print(s1 is s2)	 # True 

a1 = 'janes45613256132!@#$%#^%@$%' * 1
b1 = 'janes45613256132!@#$%#^%@$%' * 1
print(a1 is b1) # True

s1 = 'hah_' * 6
s2 = 'hah_' * 6
print(s1 is s2) # True

2.小数据池

Python 自动将 -5~256 的整数进行了缓存,当你将这些整数赋值给变量时,并不会重新创建对象,而是使用已经创建好的缓存对象;
Python会将满足一定规则的字符串在字符串驻留池中,创建一份,当你将这些字符串赋值给变量时,并不会重新创建对象, 而是使用在字符串驻留池中创建好的对象;
bool 值就是 True,False,无论你创建多少个变量指向 True,False,它在内存中都只存在一个;

小数据池也是只针对 int(float),str,bool;
小数据池是针对不同代码块之间的缓存机制;

# cmd, -5~256 的小整数虽然不在同一代码块中, 但是它们适用小数据池机制
>>>a = 245
>>>b = 245
>>>a is b # True
# 长度为0与1的字符串一定会被驻留;
# 字符串驻留发生在程序编译时;
# 被驻留的字符串必须由 ASCll字母, 数字以及下划线组成;
>>>s1 = '@'
>>>s2 = '@'
>>>s1 is s2 # True

>>>s1 = ''
>>>s2 = ''
>>>s1 is s2 # True

>>>s1 = 'a_b_c'
>>>s2 = 'a_b_c'
>>>s1 is s2 # True

>>>s1 = 'a b_c'
>>>s2 = 'a b_c'
>>>s1 is s2 # False

>>>s1 = 'a_b_c' * 1
>>>s2 = 'a_b_c' * 1
>>>s1 is s2 # True

>>>s1 = 'abd_d23' * 3
>>>s2 = 'abd_d23' * 3
>>>s1 is s2 # True

>>>a, b = "some_thing!", "some_thing!"
>>>a is b # False

>>>a, b = "some_thing", "some_thing"
>>>a is b # True
a1 = 1000
b1 = 1000
a1 is b1 # True

class C1(object): 
   a = 100
   b = 100
   c = 1000
   d = 1000
 
 
class C2(object):
   a = 100
   b = 1000

print(C1.a is C1.b)  # True
print(C1.a is C2.a)  # True
print(C1.c is C1.d)  # True
print(C1.c is C2.b)  # False

3.优缺点

优点:值相同的字符串的(比如标识符),直接从池里拿来用,避免频繁的创建和销毁,提升效率,节约内存;

缺点:拼接字符串、对字符串修改之类的影响性能;
因为是不可变的,所以对字符串修改不是 inplace 就地操作,要新建对象,这也是为什么拼接多字符串的时候不建议用 + 而用 join();
join() 是先计算出所有字符串的长度,然后一一拷贝,只 new 一次对象;

小整数对象池

为避免整数频繁申请和销毁内存空间,python 使用了小整数对象池,Python 对小整数的定义是 [-5, 256] ,这些整数对象是提前建立好的,不会被垃圾回收;
一个 Python 程序中,无论这个整数处于 LEGB 中哪个位置,所有位于这个范围内的整数使用的都是同一个对象;

# 3.7.5, ipython7.18.1
a = -5
b = -5
a is b # True

a = -6
b = -6
a is b # False

a = 256
b = 256
a is b # True

a = 257
b = 257
a is b # Flase

大整数对象池

cmd 终端中,大整数每赋值一次,每次的大整数都会重新创建,Pycharm 中,每次运行时,所有代码都加载到内存中,属于一个整体,所以这个时候会有一个大整数对象池处于一个代码块的大整数是同一个对象;
c 和 d 处于一个代码块,而 C1.b 和 C2.b 分别有自己的代码块,所以不相等;

# cmd 终端
a = 1000
b = 1000
a is b # False
--------------------
class C1(object): 
   a = 100
   b = 100
   c = 1000
   d = 1000
 
 
class C2(object):
   a = 100
   b = 1000

print(C1.a is C1.b)  # True
print(C1.a is C2.a)  # True
print(C1.c is C1.d)  # True ?? 难道 cmd 中也有大整数池 ?? 类加载的时候是在一块内存中,同值同地址 ?? 
print(C1.c is C2.b)  # False

# pycharm 等编辑器中
a = 1000
b = 1000
a is b # True
--------------------
class C1(object): 
   a = 100
   b = 100
   c = 1000
   d = 1000
 
 
class C2(object):
   a = 100
   b = 1000

print(C1.a is C1.b)  # True
print(C1.a is C2.a)  # True
print(C1.c is C1.d)  # True
print(C1.c is C2.b)  # False

字符串驻留机制

  Python 解释器为了提高字符串使用的效率和使用性能,编译时,使用了 intern(字符串驻留)技术来提高字符串效率,什么是 intern 机制?即值同样的字符串对象仅仅会保存一份,放在一个字符串储蓄池中,是共用的,当然,肯定不能改变,这也决定了字符串必须是不可变对象(整数类型也是不可变对象)??,浮点数就不行 ;

简单原理:

  实现 Intern 保留机制的方式非常简单,就是通过维护一个字符串储蓄池,这个池子是一个字典结构,编译时,如果字符串已经存在于池子中就不再去创建新的字符串,直接返回之前创建好的字符串对象,如果之前还没有加入到该池子中,则先构造一个字符串对象,并把这个对象加入到池子中去,方便下一次获取。;
  但是,解释器内部对intern 机制的使用策略是有考究的,有些场景会自动使用 intern ,有些地方需要通过手动方式才能启动,看下面几个常见情景:

# cmd 中浮点数没有被缓存
a = 1.0
b = 1.0
a is b # False

# cmd 中并非全部的字符串都会采用intern机制; 仅 包括下划线、数字、字母的字符串才会被 intern--类标识符
s1="hello"
s2="hello"
s1 is s2 # True

# 如果有空格,默认不启用intern机制
s1="hell o"
s2="hell o"
s1 is s2 # False

s1 = "hell!*o"
s2 = "hell!*o"
print(s1 is s2) # False

# 如果一个字符串长度超过20个字符,不启动intern机制 -- 看网上很多都是这么写的, 不超过二十个就为真,但是我在自己 3.7/8.5 版本上试了一下,发现好像没有限制,不知道是 Python 更新了,还是什么问题……
s1 = "a" * 20
s2 = "a" * 20
s1 is s2 # True

s1 = "a" * 21
s2 = "a" * 21
s1 is s2 # True

s1 = "ab" * 10
s2 = "ab" * 10
s1 is s2 # True

s1 = "ab" * 11
s2 = "ab" * 11
s1 is s2 # True

# 'kz' + 'c' 编译时已经变成 'kzc',而 s1 + 'c' 中 s1 是变量, 会在运行时进行拼接,所以没有被intern?
'kz' + 'c' is 'kzc' # True

s1 = 'kz'
s2 = 'kzc'
s1+'c' is 'kzc' # False

# pycharm 等编辑器中,只要是同一个字符串,都为 True,并不用是下划线、数字、字母的字符串
s1 = "hell o"
s2 = "hell o"
print(s1 is s2) # True

s1 = "hell!*o"
s2 = "hell!*o"
print(s1 is s2) # True

s1 = "a" * 20
s2 = "a" * 20
print(s1 is s2) # True

s1 = "a" * 21
s2 = "a" * 21
print(s1 is s2) # True

s1 = "ab" * 10
s2 = "ab" * 10
print(s1 is s2) # True

s1 = "ab" * 11
s2 = "ab" * 11
print(s1 is s2) # True

'kz' + 'c' is 'kzc' # True

s1 = 'kz'
s2 = 'kzc'
s1+'c' is 'kzc' # False

# 编辑器中,float 也被缓存了
a = 1.0
b = 1.0
a is b

以上就是详解Python 小数据池和代码块缓存机制的详细内容,更多关于Python 小数据池和代码块缓存机制的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python访问sqlserver示例
Feb 10 Python
Python简单读取json文件功能示例
Nov 30 Python
python tensorflow基于cnn实现手写数字识别
Jan 01 Python
Python利用字典将两个通讯录文本合并为一个文本实例
Jan 16 Python
Python 实现取矩阵的部分列,保存为一个新的矩阵方法
Nov 14 Python
windows上安装python3教程以及环境变量配置详解
Jul 18 Python
Python从列表推导到zip()函数的5种技巧总结
Oct 23 Python
Python PyInstaller库基本使用方法分析
Dec 12 Python
django 实现简单的插入视频
Apr 07 Python
Python如何执行精确的浮点数运算
Jul 31 Python
通过实例解析python subprocess模块原理及用法
Oct 10 Python
Python代码实现双链表
May 25 Python
浅谈Python列表嵌套字典转化的问题
Apr 07 #Python
python pyhs2 的安装操作
Apr 07 #Python
python3 sqlite3限制条件查询的操作
Apr 07 #Python
python实现高效的遗传算法
解决hive中导入text文件遇到的坑
Apr 07 #Python
python - asyncio异步编程
Apr 06 #Python
python - timeit 时间模块
Apr 06 #Python
You might like
一个简单的MySQL数据浏览器
2006/10/09 PHP
php压缩HTML函数轻松实现压缩html/js/Css及注意事项
2013/01/27 PHP
php使用curl抓取qq空间的访客信息示例
2014/02/28 PHP
php版微信发红包接口用法示例
2016/09/23 PHP
PHP封装的page分页类定义与用法完整示例
2018/12/24 PHP
JSON扫盲帖 JSON.as类教程
2009/02/16 Javascript
javascript中验证大写字母、数字和中文
2014/01/15 Javascript
巧用replace将文字表情替换为图片
2014/04/17 Javascript
jquery实现简单的自动播放幻灯片效果
2015/06/13 Javascript
javascript实现图片延迟加载方法汇总(三种方法)
2015/08/27 Javascript
jQuery+Ajax+PHP+Mysql实现分页显示数据实例讲解
2015/09/27 Javascript
jQuery自动完成插件completer附源码下载
2016/01/04 Javascript
Bootstrap安装环境配置教程分享
2016/05/27 Javascript
精彩的Bootstrap案例分享 重点在注释!(选项卡、栅格布局)
2016/07/01 Javascript
Jquery根据浏览器窗口改变调整大小的方法
2017/02/07 Javascript
JavaScript表单验证的两种实现方法
2017/02/11 Javascript
利用JavaScript实现栈的数据结构示例代码
2017/08/02 Javascript
layui之select的option叠加问题的解决方法
2018/03/08 Javascript
jquery ajaxfileuplod 上传文件 essyui laoding 效果【防止重复上传文件】
2018/05/26 jQuery
Vue表单demo v-model双向绑定问题
2018/06/29 Javascript
Bootstrap fileinput 上传新文件移除时触发服务器同步删除的配置
2018/10/08 Javascript
JS实现求5的阶乘示例
2019/01/21 Javascript
微信小程序用户授权,以及判断登录是否过期的方法
2019/05/10 Javascript
Jquery实现获取子元素的方法分析
2019/08/24 jQuery
vue 在单页面应用里使用二级套嵌路由
2020/12/19 Vue.js
在Python中的Django框架中进行字符串翻译
2015/07/27 Python
Python制作简易版小工具之计算天数的实现思路
2020/02/13 Python
Python 如何展开嵌套的序列
2020/08/01 Python
基于Python的一个自动录入表格的小程序
2020/08/05 Python
以设计师精品品质提供快速时尚:Mostata
2019/05/10 全球购物
创建省级文明单位实施方案
2014/02/27 职场文书
公共机构节能宣传周活动总结
2014/07/09 职场文书
2014年酒店工作总结与计划
2014/11/17 职场文书
2015年社区关工委工作总结
2015/04/03 职场文书
2016年安康杯竞赛活动总结
2016/04/05 职场文书
用Python将库打包发布到pypi
2021/04/13 Python