Int值的奇数Python ID分配==>不一致的'是'操作

时间:2017-12-26 19:02:26

标签: python python-3.x python-3.6

所以Python 3.6.2有一些奇怪的行为,他们为整数值赋值id。

对于[-5,256]范围内的任何整数值,分配给定值的任何变量也将被赋予与具有相同值的任何其他变量相同的ID。这种效果可以在下面看到。

>>> a, b = -5, -5
>>> id(a), id(b)
(1355597296, 1355597296)
>>> a, b = -6, -6
>>> id(a), id(b)
(2781041259312, 2781041260912)

事实上,要查看ID对的动作,您可以运行这个简单的程序,打印出我正在谈论的范围内的数字和ID ...

for val in range(-6, 258):
    print(format(val, ' 4d'), ':', format(id(val), '11x'))

如果你添加一些超出这个范围的值的其他变量,你会在python解释器中看到边界条件(即-6和257)值id的变化,但这里的值不会出现。

这意味着(至少对我而言)Python已经自由地对包含看似任意数字范围内的值的变量的地址进行硬编码。

实际上,对于初学Python学习者来说这可能有点危险:因为在初学者的正常操作范围内分配的ID是相同的,他们可能倾向于使用可能使他们遇到麻烦的逻辑,即使它看似有效,但也很有意义......

一个可能(虽然有点奇怪)的问题可能是打印一个递增的数字:

a = 0
b = 10
while a is not b:
    a = a + 1
    print(a)

这种逻辑虽然不是标准的Pythonic方式,但只要b在静态定义的数字范围内,就可以正常工作[-5。 256]

但是,只要b超出此范围,我们就会看到同样奇怪的行为。在这种情况下,它实际上会将代码抛入无限循环。

我知道使用'is'来比较值确实不是一个好主意,但是当使用'is'运算符时会产生不一致的结果,并且对于该语言的新手来说并不是很明显,并且它会是对于错误使用这种方法的新程序员来说尤其令人困惑。

所以我的问题是...... a)为什么(Python编写的行为是这样的),和 b)是否应该改变?

P.S。为了在可用的脚本中正确地演示范围,我不得不做一些奇怪的调整,这些调整确实是不正确的代码。但是,我仍然持有我的论点,因为如果这个奇怪的故障不存在,我的方法就不会显示任何结果。

for val in range(-6, 300):
    a = int(float(val))
    b = int(float(val))
    print(format(a, ' 4d'), format(id(a), '11x'), ':',format(b, ' 4d'), format(id(b), '11x'), ':', a is b)
    val = val + 1

float(int(val))是强制Python为每个值赋予一个新地址/ id而不是指向它正在访问的对象的指针所必需的。

1 个答案:

答案 0 :(得分:0)

这是Python记录的行为:

  

当前实现为-5到256之间的所有整数保留一个整数对象数组,当您在该范围内创建一个int时,实际上只返回对现有对象的引用。   source

它有助于节省内存并使操作更快一些。 它是特定于实现的。例如,IronPython的范围介于-1000和1000之间,它重新使用整数。