该
is
运营商不匹配变量的值,但这些实例本身。
到底是什么意思
我声明了两个变量,x
并y
在两个变量中分配了相同的值,但是当我使用is
运算符时,它返回false 。
我需要澄清。这是我的代码。
x = [1, 2, 3]
y = [1, 2, 3]
print(x is y) # It prints false!
该
is
运营商不匹配变量的值,但这些实例本身。
到底是什么意思
我声明了两个变量,x
并y
在两个变量中分配了相同的值,但是当我使用is
运算符时,它返回false 。
我需要澄清。这是我的代码。
x = [1, 2, 3]
y = [1, 2, 3]
print(x is y) # It prints false!
Answers:
您误解了is
操作员的测试内容。它测试两个变量是否指向同一对象,而不是两个变量具有相同的值。
从is
操作员文档中:
运算符
is
和is not
对象标识测试:x is y
当且仅当x
和y
是相同对象时为true 。
改用==
运算符:
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
告诉您两个名称是否指向一个相同的对象。==
告诉您两个名称是否引用具有相同值的对象。
A is B
与相同id(A) == id(B)
。
id(A)
在变量中,以后希望variable == id(B)
它仍然可以工作;如果A
在此期间被删除,则B
可以被赋予相同的存储位置。
\n
>>> y = 5 \n
>>> x是y \n
True \n
>>> x == y \n
True \n
>>>\n
另一个重复是在问为什么两个相等的字符串通常不相同,在这里并没有真正回答:
>>> 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
在两种情况下始终使用:
x is None
。x
会影响时y
。w
和z
由于编译器的折叠值而相同,为什么即使在使用REPL时也是如此,即使id()
在检查引用时也是如此?在Python 3.7上使用REPL
由重复的问题提示,此类推可能会起作用:
# - 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
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
>>>
希望有帮助。
-5
或高于256
Python的所有内容均为False。Python会缓存[-5,256]范围内的数字。
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
您可以在此处检查一个小的整数。257以上的数字不是一个小整数,因此将其计算为另一个对象。
==
在这种情况下,最好使用替代方法。
更多信息在这里:http : //docs.python.org/2/c-api/int.html
X指向一个数组,Y指向另一个数组。这些数组是相同的,但是is
运算符将查看不相同的那些指针。
is
操作员的功能可以显示这一点。
id
除非您要求,否则某些对象甚至都不会具有。
一个简单的例子,水果
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
这是因为==运算符仅比较变量的内容。要比较2个变量的标识,请使用is运算符
要打印标识号:
print ( id( variable ) )