Python:在使用PyCharm和IDLE / python时得到不同的结果

9
我刚刚阅读了关于“is运算符的意外结果”的内容,这是因为Python在-5到256之间缓存数字。
这个问题在以下两个链接中讨论过: "is" operator behaves unexpectedly with integers"is" and "id" in Python 3.5 当我运行其中一个示例时,在Python IDLE和Python IDE(我使用的是Jetbrains Pycharm专业版-5.0.4)之间会得到不同的结果。
在使用Python IDLE时,这是结果:
a = 1000
b = 1000
print (a is b) # prints False

使用Pycharm 5.0.4时,这是结果:
a = 1000
b = 1000
print (a is b) # prints True

这怎么可能呢? 我已经重新检查了,我的项目的Python解释器在两种情况下完全相同(都是Python 3.5.1)。 不确定这是我做错了什么,希望有人能解释一下。
编辑: 我知道'a'是'b' == true当且仅当id(a) == id(b),并且您可以像评论中提到的那样进行检查。也许我应该更清楚,我不明白的是一个IDE怎么会有不同的行为?我认为(如果我错了,请纠正我),IDE只是使用外部编译器/解释器的用户友好环境,因此它们独立于这些IDE(例如,pycharm不仅支持Python,我可以运行带有C编译器或Java等的Eclipse等所有这些都不是IDE的一部分)。
谢谢, 艾伦。
3个回答

5
这是因为LOAD_CONST字节码的工作方式:

co_consts [consti]推入堆栈。

由于整数被存储为常量,因此在相同上下文中对同一整数进行赋值将产生完全相同的结果,我们可以看到LOAD_CONST的参数对于a和b都是0
>>> import dis
>>> dis.dis("a = 1000 ; b = 1000")     
  1           0 LOAD_CONST               0 (1000)
              3 STORE_NAME               0 (a)
              6 LOAD_CONST               0 (1000)
              9 STORE_NAME               1 (b)
             12 LOAD_CONST               1 (None)
             15 RETURN_VALUE
                                       # ^ this is the argument 

在交互式会话中,每个命令都是单独编译的(以便可以单独执行),因此常量将会不同:

>>> code1 = compile("a = 1000","<dummy file>","exec")
>>> code2 = compile("a = 1000","<dummy file>","exec")
>>> code1.co_consts, code2.co_consts
((1000, None), (1000, None))
>>> code1.co_consts[0] is code2.co_consts[0]
False

同样,函数中的常数始终相同,但与其他函数中的常数不同:
def f():
    return 1000
def g():
    return 1000 #different code object!!

#these all work
assert f() is f()
assert g() is g()
assert f() is not g()
assert f() is not 1000 and g() is not 1000

注意,正如@AniMenon所指出的那样,-5到256之间的数字是为了优化而使用的单例模式,因此该范围内的数字不具备这种特性。

3

is运算符的文档中可以得知:

isis not运算符用于检查对象的身份:x is y仅在x和y是同一个对象时为真。

现在让我们来看看IDLE:

>>> a = 1000
>>> b = 1000
>>> print ( a is b )
False
>>> 
>>> 
>>> id(a)
35334812
>>> id(b)
35334800

PyCharm:

>>> a = 1000
b = 1000
print (a is b)
True
>>> id(a)
36079236
>>> id(b)
36079236

在PyCharm中,当在IDLE中不是同一个对象时,ab都是相同的对象

现在在Pycharm中有趣的是,如果像在IDLE中一样逐行输入代码,你将得到与IDLE相同的结果。

>>> a = 1000
>>> b = 1000
>>> print (a is b)
False

我的猜想是,
>>> a = 1000
    b = 1000

被优化为:

>>> a = b = 1000
>>> print (a is b)
True

所以你得到了相同的对象,因为 ab 指向同一个对象。

1
你可以通过测试 a = 1000; b = 100 + 900 或其他结果为整数1000的操作来支持你的猜测。这样就不会被优化为引用同一个对象,我想。 - Byte Commander
是的,我知道id()函数,但这不完全是我想问的。请看我的更新。无论如何,感谢您的回答。 - Alonbs
这是因为优化而不完全是你想的,因为 a = 1000; b = None ; c = 1000 也会使 a is c 为 True,你可能想看看我的回答 - Tadhg McDonald-Jensen

0

is会返回True,如果两个变量指向同一个对象, ==会返回True,如果变量所引用的对象相等。

在Python中,

>>> a = [1, 2, 3]
>>> b = a
>>> b is a 
True
>>> b == a
True

>>> b = a[:]
>>> b is a
False
>>> b == a
True

这是因为我们正在将 id(a) 与 id(b) 进行匹配。

考虑一下,

a = 1000
b = 1000
a is b

a 是 b 将会是 False;您对身份的假设仅适用于范围在 -5 至 256 的数字,这些数字由于性能原因是单例,但所有其他整数根据需要重新创建,而不是单例。

基于:reference


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接