下面是一个在互联网上非常有名的例子:

>>> a = 256
>>> b = 256
>>> a is b
True
>>> a = 257
>>> b = 257
>>> a is b
False
>>> a = 257; b = 257
>>> a is b
True

is 和 == 的区别

is 运算符检查两个运算对象是否引用自同一对象 (即, 它检查两个运算对象是否相同)

== 运算符比较两个运算对象的值是否相等

因此 is 代表引用相同, == 代表值相等.。下面的例子可以很好的说明这点:

>>> [] == []

True

>>> [] is [] # 这两个空列表位于不同的内存地址.

False

256 是一个已经存在的对象,而 257 不是

当你启动Python 的时候, 数值为 -5 到 256 的对象就已经被分配好了。这些数字因为经常被使用, 所以会被提前准备好。

Python 通过这种创建小整数池的方式来避免小整数频繁的申请和销毁内存空间。

当前的实现为-5到256之间的所有整数保留一个整数对象数组, 当你创建了一个该范围内的整数时, 你只需要返回现有对象的引用。所以改变1的值是有可能的。我怀疑这种行为在Python中是未定义行为. :-)

>>> id(256)
10922528
>>> a = 256
>>> b = 256
>>> id(a)
10922528
>>> id(b)
10922528
>>> id(257)
140084850247312
>>> x = 257
>>> y = 257
>>> id(x)
140084850247440
>>> id(y)
140084850247344

这里解释器并没有智能到能在执行 y = 257 时意识到我们已经创建了一个整数 257,所以它在内存中又新建了另一个对象。

当 a 和 b 在同一行中使用相同的值初始化时,会指向同一个对象。

>>> a, b = 257, 257
>>> id(a)
140640774013296
>>> id(b)
140640774013296
>>> a = 257
>>> b = 257
>>> id(a)
140640774013392
>>> id(b)
140640774013488

当 a 和 b 在同一行中被设置为 257 时, Python 解释器会创建一个新对象,然后同时引用第二个变量。如果你在不同的行上进行, 它就不会 "知道" 已经存在一个 257 对象了。

这是一种特别为交互式环境做的编译器优化。当你在实时解释器中输入两行的时候,他们会单独编译, 因此也会单独进行优化。如果你在 .py 文件中尝试这个例子,则不会看到相同的行为,因为文件是一次性编译的。