Python中的小数据池是为提高效率,固定数据使用同一个内存地址的内存驻留机制,使用时不需要频繁创建新对象。
小数据池只针对: 整数,字符串,布尔值。其他的数据类型不存在驻留机制。
Python程序是由代码块构造的。块是一个python程序的文本,他是作为一个单元执行的。
代码块:一个模块,一个函数,一个类,一个文件等都是一个代码块。
交互方式输入的每个命令都是一个代码块。例如:

  1. >>> m = 500 # 这是一个代码块
  2. >>> n = 500 # 这是一个代码块
  3. >>>
  4. >>> def leap(year): # 这是一个代码块
  5. print(year)

代码块的缓存机制

为了节省内存,提高效率,python有小数据池的概念,执行一个代码块时,python会先检查这个代码块是否存在,存在则重用,不存在则新建。
小数据池的缓存机制是使用范围:
代码块的缓存机制的适用范围: int(float),str,bool。
int(float):任何数字在同一代码块下都会复用。
bool:True和False在字典中会以1,0方式存在,并且复用。
str:几乎所有的字符串都会符合缓存机制

小数据池,也称为小整数缓存机制,或者称为驻留机制等等。小数据池只针对 int(float),str,bool,是针对不同代码块之间的缓存机制。
对于整数:
Python自动将 -5~256 的整数进行了缓存,将这些整数赋值给变量时,并不会重新创建对象,而是使用已经创建好的缓存对象。
对于字符串:
python会将一定规则的字符串在字符串驻留池中,创建一份,当你将这些字符串赋值给变量时,并不会重新创建对象, 而是使用在字符串驻留池中创建好的对象。
无论是缓存还是字符串驻留池,都是python做的一个优化,就是将-5~256的整数,和一定规则的字符串,放在一个‘池’(容器,或者字典)中,无论程序中那些变量指向这些范围内的整数或者字符串,那么他直接在这个‘池’中引用,言外之意,就是内存中之创建一个。
优点:
能够提高一些字符串,整数处理任务在时间和空间上的性能;需要值相同的字符串,整数的时候,直接从‘池’里拿来用,避免频繁的创建和销毁,提升效率,节约内存。
int:对于整数,小数据池的范围是-5~256 ,如果多个变量都是指向同一个数字,在内存中指向的都是一个内存地址。
str:字符串从以下几个方面讨论:

  1. 如果字符串的长度是0或者1, 都会默认进⾏缓存
  2. 字符串长度大于1, 但是字符串中只包含字⺟, 数字, 下划线时才会缓存
  3. 指定驻留. 我们可以通过sys模块中的intern()函数来指定要驻留的内容.
  4. 特殊字符(中文除外)定义一个的时候进行驻留

⽤乘法得到的字符串:
①. 乘数为1, 仅包含数字, 字⺟, 下划线时会被缓存. 如果包含其他字符, 而长度<=1 也会被驻存,
②. 乘数大于1 . 仅包含数字, 字⺟, 下线这个时候会被缓存. 但字符串长度不能大于20

  1. >>> from sys import intern
  2. >>> s1 = intern("zw左魏!#@*lp")
  3. >>> s2 = intern("zw左魏!#@*lp")
  4. >>> print(s1 is s2)
  5. True

满足以上字符串的规则时,就符合小数据池的概念。
bool值就是True,False,无论你创建多少个变量指向True,False,那么他在内存中只存在一个。
看一下用了小数据池(驻留机制)的效率有多高:
显而易见,节省大量内存在字符串比较时,非驻留比较效率o(n),驻留时比较效率o(1)。
总结:
如果在同一代码块下,则采用同一代码块下的换缓存机制。
如果是不同代码块,则采用小数据池的驻留机制。

  1. >>> s1 = 300
  2. >>> s2 = 300 # 直接python解释器运行,s1是一个代码块,s2是一个代码块
  3. >>> print(s1 is s2)
  4. False # 不同代码块走小数据池,300超出范围,所以为False
  5. #在外面创建一个文件awa.py
  6. ~ echo -e "s1 = 300\ns2 = 300\nprint(s1 is s2)" >> awa.py
  7. ~ python3.6 awa.py # 这个文件是一个代码块
  8. True # 所以直接走代码块的缓存机制为True
  9. # 注: 如果在函数内生成两个函数,则这两个函数都生成300的情况下
  10. # 因为一个函数体是一个代码块, python会为每个函数生成临时空间(开辟一块内存)

交互模式下(控制台):
  1. 1.数字:在-**5~256**之间的数值可以被缓存;<br /> 2.布尔值:<br /> 3.字符串:<br /> 字符串的长度为01时,会默认进行缓存;<br /> 字符串自己定义,**长度**不限,但字符串只包含字母,数字,下划线的时会缓存;<br /> 用乘法得到的字符串:·乘数为1,仅包含字母,数字,下划线时会缓存,如果包含其他字符, 而长度<=1 也会被驻存; ·乘数大于1,仅包含数字, 字母, 下划线这个时候会被缓存,但字符串**长度**不能大于20;<br /> 特殊字符(中文除外), 定义为 1 个字符时,会进行驻留;

在代码块内部(一个py文件):
  1. 1.数字:基本上都可以进行缓存,但是临界值没有明确的限定;运算结果-5~256之间会缓存<br /> 2.布尔值:可以进行缓存<br /> 3.字符串:默认字符串都缓存,如果有乘法运算与控制台相同;python3.7版本乘法不能超过4096<br />总结:执行同⼀个代码块时, 遇到初始化对象的命令时,他会将初始化的这个变量与值存储在一个字典中, 在遇到新的变量时, 会先在字典中查询记录, 如果有同样的记录那么它会重复使用这个字典中的之前的这个值。<br />如果是不同的代码块, 他就会看这个两个变量是否是满足小数据池的数据, 如果是满⾜小数据池的数据则会指向同⼀个地址。 所以: a, b的赋值语句分别被当作两个代码块执⾏,但是他们不满足小数据池的数据所以会得到两个不同的对象,因⽽is判断返回False。<br />**优点:** 能够提高一些字符串,整数的处理理速度,省略的创建对象的过程;<br />**缺点:** '池'中创建或者插入新的内容会花费更多的时间。

强行驻留
  1. from sys import intern ##自己进行驻留

指定驻留:通过sys模块中的intern()函数来指定驻留内容

  1. from sys import intern
  2. a = intern('hahah'*5)
  3. b = intern('hahah'*5)
  4. print(a == b) #True
  5. print(a is b) #True