首先看下面一段程序:
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。