理解Python的“是”运算符

时间:2012-11-30 17:39:15

标签: python python-3.x operators

  

is运算符与变量的值不匹配,但是   实例本身。

这究竟意味着什么?

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

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

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

print x is y #It prints false!

11 个答案:

答案 0 :(得分:153)

你误解了is运算符测试的内容。它测试两个变量是否指向相同的对象,而不是两个变量具有相同的值。

来自is operator的文档:

  

运算符isis not测试对象标识:当且仅当x is yx是同一个对象时,y才为真。

请改用==运算符:

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

但如果您要将y分配给x,则两者都指向同一个对象:

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

is显示两者都是同一个对象,它返回True

请记住,在Python中,names are just labels referencing values;您可以将多个名称指向同一个对象。 is告诉您两个名称是否指向同一个对象。 ==告诉您两个名称是否引用具有相同值的对象。

答案 1 :(得分:50)

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对如何实习有更详细的讨论。

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

好的,但为什么zw相同?

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

如果相同的编译时字符串在同一个模块中出现两次(这意味着什么难以定义 - 它与字符串文字不同,因为r'abc''abc''a' 'b' 'c'都是不同的文字,但字符串相同但直观易懂,编译器只会创建一个字符串实例,并带有两个引用。

实际上,编译器可以更进一步:优化器可以将'ab' + 'c'转换为'abc',在这种情况下,它可以与'abc'常量折叠在一起模块。

同样,这是Python允许但不需要做的事情。但在这种情况下,CPython总是折叠小字符串(以及例如小元组)。 (尽管交互式解释器的逐语句编译器不会像一次编译模块那样运行相同的优化,因此您不会以交互方式看到完全相同的结果。)


那么,作为程序员,你应该怎么做呢?

嗯......没什么。如果两个不可变值相同,您几乎没有理由关心它。如果您想知道何时可以使用a is b代替a == b,那么您就会提出错误的问题。除了两种情况外,只需使用a == b

  • 有关单身价值的可读性比较,例如x is None
  • 对于可变值,当您需要知道变异x是否会影响y

答案 2 :(得分:7)

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]

答案 3 :(得分:7)

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

答案 4 :(得分:5)

isis 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
>>>

上面的示例显示ab的身份(也可以是Cpython中的内存地址)不同(即使它们的值相同)。这就是为什么当你说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
>>>

在上面的示例中,即使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
>>>

希望有所帮助。

答案 5 :(得分:3)

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

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

更多信息请点击此处:http://docs.python.org/2/c-api/int.html

答案 6 :(得分:3)

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

正如@ tomasz-kurgan在下面的评论is中指出的那样,运算符对某些对象的行为异乎寻常。

E.g。

>>> 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 :(得分:2)

X指向数组,Y指向不同的数组。那些数组是相同的,但is运算符将查看那些不相同的指针。

答案 8 :(得分:1)

它比较对象标识,即变量是否引用内存中的同一对象。它类似于Java或C中的==(比较指针时)。

答案 9 :(得分:1)

带有水果的简单示例

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 ) )

答案 10 :(得分:-3)

function changeCssURL(themename){ $("button").click(function(){ $('link[href$="Theme.css"]').attr("href", "app.project.com/UAT/css/"+themename+".css"); }); } 运算符不过是is的英文版本。 由于两个列表的ID不同,因此答案为假。 您可以尝试:

==

*因为两个列表的ID都相同