详解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通过pil模块将raw图片转换成png图片的方法
Mar 16 Python
PyQT实现多窗口切换
Apr 20 Python
Python访问MongoDB,并且转换成Dataframe的方法
Oct 15 Python
Python数据类型之Tuple元组实例详解
May 08 Python
Python3使用TCP编写一个简易的文件下载器功能
May 08 Python
Python爬虫 批量爬取下载抖音视频代码实例
Aug 16 Python
python GUI框架pyqt5 对图片进行流式布局的方法(瀑布流flowlayout)
Mar 12 Python
借助Paramiko通过Python实现linux远程登陆及sftp的操作
Mar 16 Python
Pycharm中安装Pygal并使用Pygal模拟掷骰子(推荐)
Apr 08 Python
python使用自定义钉钉机器人的示例代码
Jun 24 Python
Python 绘制可视化折线图
Jul 22 Python
python用分数表示矩阵的方法实例
Jan 11 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
php获取域名的google收录示例
2014/03/24 PHP
功能强大的PHP发邮件类
2016/08/29 PHP
详解yii2使用多个数据库的案例
2017/06/16 PHP
php微信开发之关键词回复功能
2018/06/13 PHP
javascript表单验证 - Parsley.js使用和配置
2013/01/25 Javascript
js生成随机数之random函数随机示例
2013/12/20 Javascript
js中传递特殊字符(+,&)的方法
2014/01/16 Javascript
jQuery学习总结之jQuery事件
2014/06/30 Javascript
全面解析JavaScript中“&&”和“||”操作符(总结篇)
2016/07/18 Javascript
JS实现输入框提示文字点击时消失效果
2016/07/19 Javascript
jQuery简单设置文本框回车事件的方法
2016/08/01 Javascript
Angularjs 制作购物车功能实例代码
2016/09/14 Javascript
js querySelector() 使用方法
2016/12/21 Javascript
el表达式 写入bootstrap表格数据页面的实例代码
2017/01/11 Javascript
jQuery实现动态显示select下拉列表数据的方法
2018/02/05 jQuery
node 命令方式启动修改端口的方法
2018/05/12 Javascript
JS document内容及样式操作完整示例
2020/01/14 Javascript
JavaScript 生成唯一ID的几种方式
2021/02/19 Javascript
编写Python脚本批量下载DesktopNexus壁纸的教程
2015/05/06 Python
python实现周期方波信号频谱图
2018/07/21 Python
解决Pandas的DataFrame输出截断和省略的问题
2019/02/08 Python
初探利用Python进行图文识别(OCR)
2019/02/26 Python
详细介绍pandas的DataFrame的append方法使用
2019/07/31 Python
利用setuptools打包python程序的方法步骤
2020/01/18 Python
Keras之fit_generator与train_on_batch用法
2020/06/17 Python
selenium设置浏览器为headless无头模式(Chrome和Firefox)
2021/01/08 Python
Merrell美国官网:美国登山运动鞋品牌
2018/02/07 全球购物
Koral官方网站:女性时尚运动服
2019/04/10 全球购物
教师应聘个人求职信
2013/12/10 职场文书
学习十八大精神心得体会
2013/12/31 职场文书
单位成立周年感言
2014/01/26 职场文书
先进集体事迹材料
2014/02/17 职场文书
技术股份合作协议书
2014/10/05 职场文书
检讨书格式
2015/01/23 职场文书
员工开除通知书
2015/04/25 职场文书
go xorm框架的使用
2021/05/22 Golang