问了这样的问题。为什么只有 str 和 boolean 类型具有相同的变量才引用一个内存位置:
a = 'something'
b = 'something'
if a is b: print('True') # True
但我们没有写任何地方
a = b
。因此,解释器看到字符串彼此相等并引用了一个内存单元。
当然,如果我们为这两个变量中的任何一个分配一个新值,就不会发生冲突,所以现在该变量将引用另一个内存位置
b = 'something more'
if a is b: print('True') # False
布尔类型都一样
a = True
b = True
if a is b: print('True') # True
我首先想到所有可变类型都会发生这种情况。但没有。剩下一种不可改变的类型——元组。但它有一个不同的行为,即当我们为变量分配相同的值时,我们已经引用了不同的内存单元。为什么这种情况只发生在不可变类型的元组上
a = (1,9,8)
b = (1,9,8)
if a is b: print('True') # False
在Python中,
==
检查值是否相等,而is
检查其是否基本上是相同的对象,如下所示:id(object) == id(object)
a = 'something'
b = 'something'
id(a)
# 139702804094704
id(b)
# 139702804094704
a is b
# True
但是如果你稍微改变一下:
a = 'something else'
b = 'something else'
id(a)
# 139702804150640
id(b)
# 139702804159152
a is b
# False
我们得到了 False,因为 Python 这次对
a
和 b
使用了不同的内存位置,与之前不同。为什么某些类型会缓存值?因为你不应该注意到差异!
is
是一个非常专业的操作员。几乎总是您应该使用 ==
来代替,这将完全满足您的需求。
您想要使用
is
而不是 ==
的情况基本上是当您处理的对象已经重载了 ==
的行为而不意味着您想要它的意思,或者您担心的时候您可能正在处理此类物体。
如果您不确定是否正在处理此类对象,那么您可能不是,这意味着
==
总是正确的,您不必使用 is
。
将
is
与已知的单例对象(例如 None
)一起使用可能是“风格点”的问题,但在那里使用 ==
没有任何问题(同样,在没有 ==
的病态实现的情况下) ).
如果您正在处理潜在的不可信对象,那么您应该永远做任何可能调用它们控制的方法的事情......这是使用
is
的好地方。但几乎没有人这样做,而那些这样做的人应该意识到恶意对象可能导致问题的无数其他方式。
如果一个对象错误地实现了
==
那么你可能会遇到各种奇怪的问题。在调试这些问题的过程中,你当然可以而且应该使用is
!但这不应该是您在编写的代码中比较对象的常规方式。
您可能想要使用
is
而不是 ==
的另一种情况是作为性能优化,如果您正在处理的对象以特别昂贵的方式实现 ==
。这种情况根本不会经常发生,大多数时候有更好的方法来减少比较两个对象的次数(例如通过比较哈希码),这最终会产生更好的效果在不影响正确性的情况下关注性能。
如果您在语义上需要
equality比较的任何地方使用
==
,那么您甚至不会注意到某些类型何时偷偷地重用您的实例。
答案很简单,因为不可变对象的相同值具有不同的变量名称且具有相同的内存位置 错误的 a = (1,9,8) b = (1,9,8) 如果a是b: print('真') # 假 正确答案是 a = (1,9,8) b = (1,9,8) 如果a是b: print('真') # 真