理解“is”运算符[重复]
- 2024-11-29 08:41:00
- admin 原创
- 166
问题描述:
该
is
运算符并不匹配变量的值,而是匹配实例本身。
这究竟意味着什么?
我声明了两个名为的变量x
,并y
在两个变量中分配相同的值,但是当我使用is
运算符时,它返回 false。
我需要澄清一下。这是我的代码:
x = [1, 2, 3]
y = [1, 2, 3]
print(x is y) # False
解决方案 1:
您误解了运算符测试的内容is
。它测试两个变量是否指向同一个对象,而不是两个变量是否具有相同的值。
is
来自操作员的文档:
运算符
is
和is not
测试对象身份:x is y
当且仅当x
和y
是同一个对象时才为真。
请使用==
运算符:
print(x == y)
这将打印True
.x
和y
两个单独的列表:
x[0] = 4
print(y) # prints [1, 2, 3]
print(x == y) # prints False
如果您使用该id()
函数,您将看到x
并y
具有不同的标识符:
>>> id(x)
4401064560
>>> id(y)
4401098192
但是如果你要分配y
,x
那么两者都指向同一个对象:
>>> x = y
>>> id(x)
4401064560
>>> id(y)
4401064560
>>> x is y
True
并is
表明两者是同一个对象,它返回True
。
请记住,在 Python 中,名称只是引用值的标签;您可以让多个名称指向同一个对象。is
告诉您两个名称是否指向同一个对象。==
告诉您两个名称是否引用具有相同值的对象。
解决方案 2:
另一个重复的问题询问为什么两个相等的字符串通常不相同,但这里并没有真正回答这个问题:
>>> x = 'a'
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False
那么,为什么它们不是同一个字符串?特别是考虑到这一点:
>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True
我们先把第二部分推迟一下。第一部分怎么可能是真的呢?
解释器必须有一个“驻留表”,即一个将字符串值映射到字符串对象的表,因此每次您尝试使用内容创建新字符串时'abc'
,都会返回相同的对象。维基百科对驻留的工作原理有更详细的讨论。
并且 Python有一个字符串驻留表;您可以使用该方法手动驻留字符串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
好的,但是为什么z
和w
相同呢?
这不是解释器自动驻留,而是编译器折叠值。
如果相同的编译时字符串在同一个模块中出现两次(这到底意味着什么很难定义——它与字符串文字不同,因为r'abc'
、'abc'
和'a' 'b' 'c'
都是不同的文字但是是相同的字符串——但直观上很容易理解),编译器只会创建该字符串的一个实例,并带有两个引用。
事实上,编译器可以更进一步:'ab' + 'c'
可以被优化器转换为'abc'
,在这种情况下它可以与'abc'
同一个模块中的常量一起折叠。
再次强调,这是 Python 允许但不需要做的事情。但在这种情况下,CPython 总是折叠小字符串(以及例如小元组)。(尽管交互式解释器的逐语句编译器不会运行与一次模块编译器相同的优化,因此您不会以交互方式看到完全相同的结果。)
那么,作为一名程序员,你应该怎么做呢?
嗯……没什么。你几乎从来没有理由关心两个不可变值是否相同。如果你想知道什么时候可以使用a is b
而不是a == b
,那你就问错了。a == b
在两种情况下始终使用 except 即可:
为了与单例值进行更易读的比较,例如
x is None
。对于可变值,当您需要知道变异是否
x
会影响时y
。
解决方案 3:
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]
解决方案 4:
受重复问题的提示,这个类比可能有效:
# - 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
解决方案 5:
is
和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 中也可以是内存地址)是不同的a
(b
即使它们的值相同)。这就是为什么当您说时,a is b
它会返回 false,因为两个操作数的标识不匹配。但是当您说时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
>>>
在上面的例子中,尽管a
和b
是两个不同的变量,但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
>>>
希望有所帮助。
解决方案 6:
x is y
与 相同id(x) == id(y)
,比较对象的身份。
正如@tomasz-kurgan 在下面的评论中指出的那样,is
运算符对某些对象的行为异常。
例如
>>> class A(object):
... def foo(self):
... pass
...
>>> a = A()
>>> a.foo is a.foo
False
>>> id(a.foo) == id(a.foo)
True
参考:
https://docs.python.org/2/reference/expressions.html#is-not
https://docs.python.org/2/reference/expressions.html#id24
解决方案 7:
正如您在此处看到的,这是一个小整数。 257 以上的数字不是小整数,因此它被计算为不同的对象。
==
在这种情况下最好使用。
更多信息请参见:http: //docs.python.org/2/c-api/int.html
解决方案 8:
X 指向一个数组,Y 指向另一个数组。这两个数组是相同的,但is
运算符将查看不相同的指针。
解决方案 9:
它比较对象身份,即变量是否引用内存中的同一个对象。它类似于==
Java 或 C 中的(比较指针时)。
解决方案 10:
一个水果的简单例子
fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist is newfruitlist )
print ( fruitlist is verynewfruitlist )
print ( newfruitlist is verynewfruitlist )
输出:
True
False
False
如果你尝试
fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist == newfruitlist )
print ( fruitlist == verynewfruitlist )
print ( newfruitlist == verynewfruitlist )
输出不同:
True
True
True
这是因为 == 运算符仅比较变量的内容。要比较两个变量的身份,请使用is运算符
打印识别号码:
print ( id( variable ) )
解决方案 11:
该is
运算符只不过是 的英文版本==
。由于两个列表的 ID 不同,因此答案为 false。您可以尝试:
a=[1,2,3]
b=a
print(b is a )#True
*因为两个列表的 ID 相同