is 和 == 有什么区别?
== 和is 是不同的比较!正如其他人已经说过的那样:
在 Python 中,名称指代对象,例如在本例中,value1 和 value2 指代存储值 1000 的 int 实例:
value1 = 1000
value2 = value1
因为value2指的是同一个对象is和==会给出True:
>>> value1 == value2
True
>>> value1 is value2
True
在以下示例中,名称 value1 和 value2 指的是不同的 int 实例,即使两者都存储相同的整数:
>>> value1 = 1000
>>> value2 = 1000
因为存储相同的值(整数)== 将是True,这就是为什么它通常被称为“值比较”。但是is 将返回False,因为它们是不同的对象:
>>> value1 == value2
True
>>> value1 is value2
False
什么时候用哪个?
通常is 是一个更快的比较。这就是为什么 CPython 缓存(或者也许 reuses 会是更好的术语)某些对象,如小整数、一些字符串等。但这应该被视为 implementation detail 可以(即使不太可能)随时更改而不会发出警告。
您应该仅在以下情况下使用is:
在其他情况下,您应该使用==来检查是否相等。
我可以自定义行为吗?
== 的某些方面尚未在其他答案中提及:它是Pythons "Data model" 的一部分。这意味着可以使用__eq__ 方法自定义其行为。例如:
class MyClass(object):
def __init__(self, val):
self._value = val
def __eq__(self, other):
print('__eq__ method called')
try:
return self._value == other._value
except AttributeError:
raise TypeError('Cannot compare {0} to objects of type {1}'
.format(type(self), type(other)))
这只是一个人为的例子来说明该方法是真正被调用的:
>>> MyClass(10) == MyClass(10)
__eq__ method called
True
请注意,默认情况下(如果在类或超类中找不到__eq__ 的其他实现)__eq__ 使用is:
class AClass(object):
def __init__(self, value):
self._value = value
>>> a = AClass(10)
>>> b = AClass(10)
>>> a == b
False
>>> a == a
因此,如果您想要“更多”而不仅仅是自定义类的引用比较,那么实现 __eq__ 实际上很重要!
另一方面,您不能自定义 is 检查。如果您有相同的参考,它总是会比较只是。
这些比较是否总是返回布尔值?
因为__eq__ 可以重新实现或覆盖,所以不限于返回True 或False。它可以返回任何东西(但在大多数情况下它应该返回一个布尔值!)。
例如对于 NumPy 数组,== 将返回一个数组:
>>> import numpy as np
>>> np.arange(10) == 2
array([False, False, True, False, False, False, False, False, False, False], dtype=bool)
但is 检查将始终返回True 或False!
1 正如 Aaron Hall 在 cmets 中提到的:
通常您不应该进行任何is True 或is False 检查,因为通常在将条件 隐式转换为布尔值的上下文中使用这些“检查”(例如在@ 987654390@ 声明)。因此,进行is True 比较和隐式布尔转换比仅仅进行布尔转换所做的工作更多 - 并且您将自己限制为布尔值(不被认为是 pythonic)。
就像 PEP8 提到的:
不要使用 == 将布尔值与 True 或 False 进行比较。
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True: