首先看下面一段程序:
-
def test():
-
# example 1
-
a =
'hello'
-
b =
'hello'
-
print(a
is b)
# 输出True
-
print(a == b)
# 输出True
-
-
# example 2
-
a =
'hello world'
-
b =
'hello world'
-
print(a
is b)
# 输出False
-
print(a == b)
# 输出True
-
-
# example 3
-
a = [
1,
2,
3]
-
b = a
-
print(a
is b)
# 输出True
-
print(a == b)
# 输出True
上面的输出结果为什么有的相同,有的不相同呢?
官方文档描述is为对象标示符(object identity),而==表示的是相等。is的作用是用来检查对象的标示符是否一致,也就是两个对象在内存中的位置是否一样,而==是用来检查两个对象是否相等。
我们来看一下下面的程序,检查每个对象的id
-
def test():
-
# example 1
-
a =
'hello'
-
b =
'hello'
-
print(id(a))
# 输出2378974396344
-
print(id(b))
# 输出2378974396344
-
print(a
is b)
# 输出True
-
print(a == b)
# 输出True
-
-
# example 2
-
a =
'hello world'
-
b =
'hello world'
-
print(id(a))
# 输出2378974396344
-
print(id(b))
# 输出2033022437424
-
print(a
is b)
# 输出False
-
print(a == b)
# 输出True
-
-
# example 3
-
a = [
1,
2,
3]
-
b = a
-
print(id(a))
# 输出1641701071688
-
print(id(b))
# 输出1641701071688
-
print(a
is b)
# 输出True
-
print(a == b)
# 输出True
打印出id结果就很清晰了,只要a和b值相同,==结果输出True;只有id相同,is结果输出True。但是有一个问题,为什么example1的'hello' a is b就输出True,而example2的'hello world'就输出False。
这是因为前一种情况下Python的字符串驻留机制起了作用。对于较小的字符串,为了提高系统性能Python会保留其值的一个副本,当创建新的字符串的时候直接指向该副本即可。所以'hello'在内存中只有一个副本,a和b的id值相同,而'hello world'是长字符串,不驻留内存,Python中各自创建了对象来表示a和b,所以他们的值相同,但是id值不同。(有些编译器会对程序优化,所以is操作可能不同)。
实际python中None的比较,为什么是is None,而不是== None呢?
这是因为None在Python里是个单例对象,一个变量如果是None,它一定和None指向同一个内存地址。而==None背后调用的是__eq__,而__eq__可以被重载,下面是一个is not None但== None的例子
-
class Foo(object):
-
def __eq__(self,other):
-
return
True
-
f = Foo()
-
print(f
is
None)
# 输出False
-
print(f ==
None)
# 输出True
上面==被重载,所以输出True。