Python 不恰当地使用';不是';比较?

Python 不恰当地使用';不是';比较?,python,syntax-error,Python,Syntax Error,我(错误地?)在比较中使用了“不是”,并发现了这种奇怪的行为: >>> a = 256 >>> b = int('256') >>> c = 300 >>> d = int('300') >>> >>> a is not b False >>> c is not d True 显然,我应该使用: >>> a != b False >>>

我(错误地?)在比较中使用了“不是”,并发现了这种奇怪的行为:

>>> a = 256
>>> b = int('256')
>>> c = 300
>>> d = int('300')
>>>
>>> a is not b
False
>>> c is not d
True
显然,我应该使用:

>>> a != b
False
>>> c != d
False
但由于测试用例的价值很小,它工作了很长一段时间,直到我碰巧遇到 使用数字495

如果这是无效语法,为什么?我至少应该得到一个警告吗?

不要用is[not]来比较整数;使用==和!=相反尽管由于优化,is在当前的CPython中适用于小数字,但它是不可靠的,并且在语义上是错误的。语法本身是有效的,但是警告的好处(每次使用is时都必须检查,并且int的子类可能会有问题)大概不值得这么麻烦

这在其他地方也有介绍,但我刚才没有找到。

“is”不是检查值是否相等,而是检查两个变量是否指向同一个对象实例


int
s和
string
s在这方面令人困惑,因为
is
=
由于语言内部的工作方式,可能会产生相同的结果。

对于较小的数字,Python会重用对象实例,但是对于较大的数字,它会为它们创建新的实例

见此:

>>> a=256
>>> b=int('256')
>>> c=300       
>>> d=int('300')

>>> id(a)
158013588
>>> id(b)
158013588
>>> id(c)
158151472
>>> id(d)
158151436

这正是为什么
a
b
,而
c
不是
d

要了解发生这种情况的原因,请查看Python源代码中的Python-2.6.5/Objects/intobject.c:78:small\u ints数组和Python-2.6.5/Objects/intobjects.c:1292:_PyInt\u Init函数

列表中也会出现类似的情况:


>>> a = [12]
>>> id_a = id(a)
>>> del(a)
>>> id([1,2,34]) == id_a
True
>>> 

删除的列表不会被销毁。在python中Int是一个对象,默认情况下python缓存[-5256]之间的小整数,因此在[-5256]中使用Int时,它们是相同的

a = 256
b = 256

a is b # True
如果在[-5256]中声明了两个非整数,python将创建两个不相同的对象(尽管它们具有相同的值)

在您的情况下,请使用
=相反,比较值是正确的方法

a = 257
b = 257

a != b # False

+1该语言不保证
is
适用于小数字。一个实现可以不做这种优化是的,这一点值得强调。(然而,我不知道IronPython或Jython目前是如何工作的。)id通常是重用的,不管它们是否指向列表。这就是为什么没有可靠的id->对象映射功能的原因。但要实现这一点,必须删除第一个具有该id的对象(就像您在
dela
中所做的那样)。重用id与OP询问的低值整数优化不同。在OP的情况下,在比较id之前没有删除第一个int。>通常重复使用id是。>重用id与OP询问的低值整数优化不同。不,是一样的。关于Python-2.6.5/Objects/listobject.c:97:free_list arraymy的用法,请参见。我的观点是,您的示例显示了当一个对象被删除,另一个不同的对象被创建并回收相同的id时,id是如何被重用的。OP被一个依赖于实现的优化所迷惑,在这个优化中,简单的不可变对象有多个不同的名称类型在幕后绑定到同一个对象,但所有名称都同时处于“活动”状态—没有一个名称被“删除”。事实上,要使其生效,a)项必须相等,b)项必须不可变。您描述了一种不同但同样棘手的行为,它可以应用于任何对象类型。下面是您的警告:“当您指的是平等检查时,不要使用身份检查!”@Paul:amen!如果我可以用一个虚构的例子来展开:“当你想使用
时,千万不要使用
。is\u草莓()
。is\u红色()
”我对否决票感到困惑:如果我的答案不准确,我很想知道为什么我不会再犯同样的错误了……我想你永远也不会得到你先前评论的答案;我相信每投一次反对票都必须加上评论,但我是谁?所以我只是投了你一票。
a = 257
b = 257

a != b # False