2012-11-30 26 views
55

运算符is与变量的值不匹配,但它们的实例本身不匹配。了解Python的“is”运算符

这是什么意思?

我声明了一个名为xy在两个变量分配相同的值的两个变量,但是当我用is运算符返回false。

我需要澄清。这是我的代码。

x = [1, 2, 3] 
y = [1, 2, 3] 

print x is y #It prints false! 
+0

相关问题http://stackoverflow.com/questions/38189660/two-variables-in-python-have-same-id-but-not-lists-or-tuples-why/38189759#38189759 – Kasramvd

回答

102

您误解了is操作员测试的内容。它测试两个变量是否指向相同的对象,而不是两个变量具有相同的值。

从文档的is operator

运营商is和对象标识is not试验:x is y当且仅当xy是同一对象是真实的。

使用==操盘手:

print x == y 

这将打印Truexy是两个独立的名单

x[0] = 4 
print y # prints [1, 2, 3] 
print x == y # prints False 

如果使用id() function你会看到xy有不同的标识符:

>>> id(x) 
4401064560 
>>> id(y) 
4401098192 

,但如果你要分配给yx那么两者都指向相同的对象:

>>> x = y 
>>> id(x) 
4401064560 
>>> id(y) 
4401064560 
>>> x is y 
True 

is显示两者是相同的对象,它返回True

+2

所以,'' A是B'与'id(A)== id(B)'相同。 – imallett

+1

@imallett:如果你不把'id(A)'存储在一个变量中,并且稍后期望'variable == id(B)'仍然可以工作,那么这是同一个测试的代理。如果'A'在此期间被删除,则'B'可能被赋予相同的内存位置。 –

+0

有道理,它也是正确的; '变量'是存储以前存在的东西的属性。运行时没有办法检测到后面的用法是错误的。该标准的关键部分是“在其生命周期中,[id()]保证是唯一且恒定的,两个具有非重叠生命周期的对象可能具有相同的id()值。” – imallett

2

X指向一个数组,Y指向不同的数组。这些数组是相同的,但运算符会查看那些不相同的指针。

+4

Python没有指针。你需要加强你的术语。 –

+2

它在内部执行,就像Java和许多其他语言一样。事实上,''''运算符的功能显示了这一点。 – Neko

+4

实现细节不重要。该文档使用术语“对象标识”。你应该如此。 “操作符是和不是测试对象的身份:当且仅当x和y是同一个对象时,x是y是真的,x不是y产生反真值。 –

1

它比较对象标识,也就是变量是否引用内存中的同一个对象。它就像是Java或C中的==(比较指针时)。

2

正如你可以在这里检查一个小整数。高于257的数字不是一个小数,因此它被计算为一个不同的对象。

在这种情况下,最好使用==

进一步的信息是在这里:http://docs.python.org/2/c-api/int.html

6

is只有当它们实际上是同一个对象返回true。如果它们是相同的,那么对另一个的改变也会出现。这是一个差异的例子。

>>> x = [1, 2, 3] 
>>> y = [1, 2, 3] 
>>> print x is y 
False 
>>> z = y 
>>> print y is z 
True 
>>> print x is z 
False 
>>> y[0] = 5 
>>> print z 
[5, 2, 3] 
6

duplicate question提示,这个比喻可能工作:

# - Darling, I want some pudding! 
# - There is some in the fridge. 

pudding_to_eat = fridge_pudding 
pudding_to_eat is fridge_pudding 
# => True 

# - Honey, what's with all the dirty dishes? 
# - I wanted to eat pudding so I made some. Sorry about the mess, Darling. 
# - But there was already some in the fridge. 

pudding_to_eat = make_pudding(ingredients) 
pudding_to_eat is fridge_pudding 
# => False 
+2

可能只是个人品味(没有双关语意思),但我发现这个比喻比困难比有帮助,让我想吃布丁,当我没有在我的冰箱里:( 我认为马克兰森的答案,虽然更多无聊,可能更有教育意义 –

+1

@Tom关闭:对这个问题有很多好的答案,足以让我有轻松的空间,而且我也想要布丁 – Amadan

23

Another duplicate是问为什么两个相等的字符串一般不相同的,这是不是真的在这里回答:

>>> x = 'a' 
>>> x += 'bc' 
>>> y = 'abc' 
>>> x == y 
True 
>>> x is y 
False 

那么,他们为什么不是同一个字符串呢?尤其是考虑到这一点:

>>> z = 'abc' 
>>> w = 'abc' 
>>> z is w 
True 

让我们推迟了第二部分的位。第一个怎么可能是真的?

解释器必须有一个“实习表”,一个将字符串值映射到字符串对象的表,所以每次尝试使用'abc'的内容创建一个新字符串时,都会得到相同的对象。 Wikipedia有关如何实习的更详细的讨论。

And Python has string interning table;您可以使用sys.intern方法手动实习字符串。

事实上,Python是允许自动实习生任何一成不变的类型,但不能要求这样做。不同的实现会实习不同的值。如果你不知道你正在使用哪个实现,CPython会自动实现小整数和一些特殊的单例如False,但不是字符串(或大整数或小元组,或者是小元组,或者是小元组,或者是小元组,还要别的吗)。你可以很容易地看到这一点:

>>> a = 0 
>>> a += 1 
>>> b = 1 
>>> a is b 
True 
>>> a = False 
>>> a = not a 
>>> b = True 
a is b 
True 
>>> a = 1000 
>>> a += 1 
>>> b = 1001 
>>> a is b 
False 

OK,但为什么是zw相同?

这不是解释器自动实习,这是编译器折叠值。

如果相同的编译时间字符串在同一模块中出现两次(究竟这意味着很难定义,它是不一样的事,作为一个字符串字面量,因为r'abc''abc',并且'a' 'b' 'c'都是不同的文字,但相同的字符串 - 但直观易懂),编译器将只创建一个字符串实例,并带有两个引用。

事实上,编译器可以走得更远:'ab' + 'c'可以被优化,在这种情况下,它可以与在同一模块中的'abc'常数被折叠转换为'abc'

同样,这是Python允许但不是必须做的事情。但在这种情况下,CPython总是折叠小字符串(也是小元组)。 (虽然交互式解释的声明逐言编译器不运行相同的优化为模块-AT-一个即时编译器,所以你不会看到完全相同的结果交互。)


所以,作为程序员你应该怎么做?

呃...没什么。如果两个不可变的值是相同的,你几乎从不会有任何理由关心。如果你想知道什么时候可以使用a is b而不是a == b,那么你问的是错误的问题。只是一直使用a == b除了在两种情况下:

  • 更多可读性比较的单值一样x is None
  • 对于可变值,当您需要知道变异x是否会影响y
3

is and is not是Python中的两个身份运算符。 is运算符不会比较变量的值,但会比较变量的身份。试想一下:

>>> a = [1,2,3] 
>>> b = [1,2,3] 
>>> hex(id(a)) 
'0x1079b1440' 
>>> hex(id(b)) 
'0x107960878' 
>>> a is b 
False 
>>> a == b 
True 
>>> 

上面的例子显示,你的身份(也可以在CPython的内存地址)是两个ab不同(即使它们的值是相同的)。这就是为什么当你说a is b时,由于两个操作数的身份不匹配,它会返回错误。但是,当您说a == b时,它会返回true,因为==操作仅验证两个操作数是否具有分配给它们的相同值。

有趣的例子(为特级):

>>> del a 
>>> del b 
>>> a = 132 
>>> b = 132 
>>> hex(id(a)) 
'0x7faa2b609738' 
>>> hex(id(b)) 
'0x7faa2b609738' 
>>> a is b 
True 
>>> a == b 
True 
>>> 

在上面的例子中,即使ab是两个不同的变量,a is b回到True。这是因为a的类型是int这是一个不可变的对象。所以python(我想要节省内存)分配相同的对象b当它被创建具有相同的值。所以在这种情况下,变量的身份匹配和a is b竟然是True

这将适用于所有不可变对象:

>>> del a 
>>> del b 
>>> a = "asd" 
>>> b = "asd" 
>>> hex(id(a)) 
'0x1079b05a8' 
>>> hex(id(b)) 
'0x1079b05a8' 
>>> a is b 
True 
>>> a == b 
True 
>>> 

希望有所帮助。

+0

这是一个很好的例子,谢谢你的详细信息 – Haranadh

+0

但是试试 a = 123456789 b = 123456789 – user2183078

3

x is yid(x) == id(y)相同,比较对象的身份。