为什么 "num3 is num4" 会导致 False?

Why should "num3 is num4" result in False?

Instagram 上有 this post 作者说如果 num3num4 设置为 257 并且 num3 is num4 被评估你应该得到False.

我修改了代码,添加了一些条件,但我得到了 True。我看到直到 256 的整数都被分配了相同的内存桶以获得相同的值,但对于 257 以后的整数则没有。那么发生了什么?

num1 = 256
num2 = 256

if num1 == num2:
    print(True)

num3 = 257
num4 = 257

if num3 == num4:
    print(True)
    if num3 is num4:
        print(True)
    else:
        print(False)

如果您再次查看 post,您会发现 num3 == num4 是 True, num3 is num4 是 False。这与项目 ID 有关。 == 比较变量的值,而 is 比较它们的 id。您可以使用 id(num3)id(num4) 查看他们的每个 ID。当值高于 256 时它们应该不同。原因是 Python 自动存储低数值,分配给这些低数值的变量将指向相同的 id。 Python 这样做是因为它们很常用。但是直到 Python 需要它们时才会创建更大的数字。所以变量有自己的ID。

编辑:

运行 脚本与 REPL 似乎有不同的行为。最初的 Instagram post 使用的是 REPL,我使用 REPL 复制了 False 比较。 运行 一个脚本对我来说是正确的。

is will return True if two variables point to the same object

== if the objects referred to by the variables are equal.

运行 在脚本中:

is returns True

因为 num3 和 num4 都指向同一个对象:

# id() to get the unique identifier of an object    
print(id(num3) , id(num4)) 

55080624 55080624

== also returns True

num3 = 257
num4 = 257

因为两者都指的是 <class 'int'> 257

运行 在 REPL 中:

is returns False

因为 num3 和 num4 指向不同的对象:

# id() to get the unique identifier of an object    
print(id(num3) , id(num4)) 

34836272 39621264

== returns True

num3 = 257
num4 = 257

因为两者都指的是 <class 'int'> 257

你有不同结果的原因是 Why does the `is` operator behave differently in a script vs the REPL?

When you run code in a .py script, the entire file is compiled into a code object before executing it. In this case, CPython is able to make certain optimizations - like reusing the same instance for the integer 300.

所以在你的例子中,num3 和 num4 都指的是 <class 'int'> 257。在 REPL 中你有不同的对象 ID,但是在文件被编译并优化为相同的对象 ID 之后,如果你在脚本中 运行 它们。

关于256和257的不同行为:

"is" operator behaves unexpectedly with integers

What's with the integer cache maintained by the interpreter?

简而言之,表示值从 -5 到 +256 的对象是在启动时创建的,所以如果你的数字范围是 -5 到 256,你在 REPL 中得到相同的对象 ID,对于任何 int <-5 和 > 256,他们将被分配给一个新的对象id。

例如:

num5 = -6
num6 = -6 

print(id(num5),id(num6))

39621232 39621136

num7 = 258
num8 = 258

print(id(num7),id(num8))

39621296 39621328