Python中小整数对象池和字符串实习生的示例分析

  介绍

这篇文章将为大家详细讲解有关Python中小整数对象池和字符串实习生的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

是用于判断两个对象是否为同一个对象,具体来说是两个对象在内存中的位置是否相同。

Python为了提高效率,节省内存,在实现上大量使用了缓冲池技术和字符串实习生技术。

整数和字符串是不可变对象,也就意味着可以用来共享,如100个“Python”字串变量可以共享一个“Python”字符串对象,而不是创建100个“Python”字符串。

<强>小整数对象池

为了应对小整数的频繁使用,Python使用对小整数进行了缓存,默认范围为[-5256],在这个范围内的所有整数被Python完全地缓存,当有变量使用这些小整数时,增加对应小整数对象的引用即可。

在祝辞祝辞,小姐:=5   在祝辞祝辞j =, 5   在祝辞祝辞,小姐:is  j  #, i和j是同一个对象   真正的   在祝辞祝辞,小姐:=256   在祝辞祝辞j =, 256   在祝辞祝辞,小姐:is  j  #, i和j是同一个对象   真正的   在祝辞祝辞,小姐:=257   在祝辞祝辞j =, 257   在祝辞祝辞,小姐:is  j  #, i和j是不同对象   假

由上面的实例可以看的到,当变量在[-5256]之间时,两个值相同的变量事实上会引用到同一个小整数对象上,也就是小整数对象池中的对象,而不会去创建两个对象。而当变量超出了这个范围,两个值相同的变量也会各自创建整数对象,所以两者对应的对象不同。

<强>字符串实习生

如果当前变量引用的字符串对象已经存在的话,直接增加对应字符串对象的引用,而不去创建新的字符串对象,这就是字符串实习生机制。

,在在在我=?2“
,在在在j=?2“
,在在在我是j
,真的

在详细探讨字符串实习生机制之前,先看一个奇怪的问题:

,在在在我=? 2“
,在在在j=? 2“
,在在在我是j
,假

, i=? 2“
, j=? 2“
,打印(我是j)

输出结果

,真正

上述代码分开运行,结果为False,但是合在一起结果却为真,也就是说分开运行的时候,i, j指向不同对象,而合在一起的时候,j却指向了相同对象。为了明白其中的缘由,需要简单理解python的编译机制。

编译机制

在python中,万物皆对象,包括代码本身也是一种对象.python用代码对象表示代码,代码编译后产生代码对象。通常一个作用域对应一个代码对象。

小姐:=,,1,2,   j =,, 1, 2,   print(小姐:is  j)      def  f ():   通过才能

编译结果

2 0 LOAD_CONST 0 (& # 39; 1 2 & # 39;)
2 STORE_NAME 0 (i)

3 4 LOAD_CONST 0 (& # 39; 1 2 & # 39;)
6 STORE_NAME 1 (j)

5 8 LOAD_CONST 1 (f (0) x00000200f257cf60 & lt;代码对象,文件“small_int.py",第5行祝辞)
10 LOAD_CONST 2 (& # 39; f # 39;)
12 MAKE_FUNCTION 0
14 STORE_NAME 2 (f)
16 LOAD_CONST 3(没有)
18 RETURN_VALUE

拆卸& lt; f (0) x00000200f257cf60代码对象,文件“small_int.py"第5行祝辞:
6 0 LOAD_CONST 0(没有)
2 RETURN_VALUE

上述代码中编译生成了两个代码对象,一个代表全局作用域,另一个代表函数f。

代码对象保存了变量,常量(常量字面量)以及编译结果.code对象用常量表来保存常量,考虑到一个常量可能出现多次,在一张表上保存一个常量多次太过于奢侈。所以代码对象对每个常量只保存一次,在需要引用它的地方使用它在常量表的位置作为常量的表示。在上述编译结果中可以看的到,“1 2“这个字符串常量使用了两次,编译的代码为“LOAD_CONST 0“,这里的0就是“1 2“在常量表当中的位置。

由于编译的这个特性,在同一个代码对象中的变量,如果它们引用了同一个常量,那么无论这个常量有没有缓冲机制,它们引用的都是同一个对象。

a =,“12”;   时间=b “12”;   c =,, 1, 2,   d =,, 1, 2,   e =257   f =257   g =2424234234234234   h =2424234234234234   print (a  is  b, c  is  d, e  is  f, g  is  h)

输出结果

,真的真的真的真的

这个例子说明,在同一个代码对象当中,常量(字面量)仅一份,这与缓冲机制无关,是编译特性。所以对于上述那个奇怪的问题就可以解释了,当我,j在同一个代码对象(同一个作用域)中引用常量“1 2“,它们引用的都是同一个对象。而当在python命令行中分开执行时,对于每一条语句,都是一个单独的代码对象,这时起作用的是字符串实习生机制,上述运行结果说明,字符串实习生机制对“12”;进行了实习生,而对“1 2“没有进行实习生。

Python中小整数对象池和字符串实习生的示例分析