为什么“ num3是num4”会导致False?

时间:2020-01-21 02:08:12

标签: python python-3.x int python-internals

Instagram上有this条帖子,作者说,如果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)

2 个答案:

答案 0 :(得分:3)

如果两个变量指向同一个对象,

is将返回True

==如果变量引用的对象相等。

在脚本中运行:

返回True

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

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

55080624 55080624

== 也返回True

num3 = 257
num4 = 257

两者均指<class 'int'> 257

在REPL中运行:

返回False

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

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

34836272 39621264

== 返回True

num3 = 257
num4 = 257

两者均指<class 'int'> 257

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

在.py脚本中运行代码时,整个文件将被编译为 代码对象,然后再执行。在这种情况下,CPython能够 某些优化-例如为整数重用同一实例 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之间,则对于任何<-5和> 256的int,在REPL中都会获得相同的对象ID,它们将被分配给新的对象ID。

例如:

num5 = -6
num6 = -6 

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

39621232 39621136

num7 = 258
num8 = 258

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

39621296 39621328

答案 1 :(得分:2)

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

编辑:

运行脚本与REPL时似乎有不同的行为。最初的Instagram帖子使用REPL,我使用REPL复制了False比较。不过,运行脚本对我来说是True。