为什么下面的代码在Python中会出现意外的行为?

>>> a = 256
>>> b = 256
>>> a is b
True           # This is an expected result
>>> a = 257
>>> b = 257
>>> a is b
False          # What happened here? Why is this False?
>>> 257 is 257
True           # Yet the literal numbers compare properly

我使用的是Python 2.5.2。尝试一些不同版本的Python,似乎Python 2.3.3在99到100之间显示了上述行为。

基于以上,我可以假设Python是内部实现的,这样“小”整数与大整数以不同的方式存储,并且is操作符可以区分两者。为什么会有漏洞的抽象?有什么更好的方法来比较两个任意物体来判断它们是否相同当我事先不知道它们是否是数字时?


当前回答

看看这个:

>>> a = 256
>>> b = 256
>>> id(a)
9987148
>>> id(b)
9987148
>>> a = 257
>>> b = 257
>>> id(a)
11662816
>>> id(b)
11662828

以下是我在“普通整数对象”的文档中找到的:

当前的实现为-5到256之间的所有整数保留了一个整数对象数组。当你在这个范围内创建一个int型时,你实际上只是得到了一个对现有对象的引用。

其他回答

我认为你的假设是正确的。实验id(对象的身份):

In [1]: id(255)
Out[1]: 146349024

In [2]: id(255)
Out[2]: 146349024

In [3]: id(257)
Out[3]: 146802752

In [4]: id(257)
Out[4]: 148993740

In [5]: a=255

In [6]: b=255

In [7]: c=257

In [8]: d=257

In [9]: id(a), id(b), id(c), id(d)
Out[9]: (146349024, 146349024, 146783024, 146804020)

似乎数字<= 255被视为字面量,以上任何数字都被区别对待!

看看这个:

>>> a = 256
>>> b = 256
>>> id(a)
9987148
>>> id(b)
9987148
>>> a = 257
>>> b = 257
>>> id(a)
11662816
>>> id(b)
11662828

以下是我在“普通整数对象”的文档中找到的:

当前的实现为-5到256之间的所有整数保留了一个整数对象数组。当你在这个范围内创建一个int型时,你实际上只是得到了一个对现有对象的引用。

这取决于你要看的是两个物体是否相等,还是同一个物体。

是检查它们是否是相同的对象,而不仅仅是相等。较小的int可能指向相同的内存位置以提高空间效率

In [29]: a = 3
In [30]: b = 3
In [31]: id(a)
Out[31]: 500729144
In [32]: id(b)
Out[32]: 500729144

您应该使用==来比较任意对象的相等性。你可以用__eq__和__ne__属性来指定行为。

正如你可以检入源文件inobject .c一样,Python缓存小整数以提高效率。每次创建对小整数的引用时,引用的都是缓存的小整数,而不是新对象。257不是一个小整数,所以它是作为一个不同的对象计算的。

为了这个目的,最好使用==。

对于不可变值对象,比如int、字符串或datetimes,对象标识并不是特别有用。最好还是考虑一下平等。标识本质上是值对象的实现细节——因为它们是不可变的,所以对同一个对象的多次引用和对多个对象的多次引用之间没有有效的区别。