在python中,检查对象是否为none时,为什么首选”is”而不是”==”

In python, why 'is' is preferred over '==' for checking if object in None

本问题已经有最佳答案,请猛点这里访问。

如果我写这个:

1
2
if x == None:
    x = 1

我的Pycharm编辑器一直建议我应该使用"is"而不是"==":

1
2
if x is None:
    x = 1

对于任何其他平等检查,Pycharm不建议使用"is",例如:

1
2
if x == 2:
    x = 1

为什么在检查对象是否为None时,'is'运算符比'=='运算符更受欢迎?

为什么只对None首选?


因为None是单例的,所以在python程序中对象只有一个副本。

在对单个对象进行测试时,is更快,因为只有指针需要相等。==测试更多信息,在这种情况下,测试对象的状态也需要相同。

如果您的x对象实现了一个自定义的object.__eq__()方法,这一点会更加明显;每次使用x == None时都会调用它,而x is None没有这样的钩子。这意味着每次执行相等测试时,解释器必须执行更多的Python代码。我是否已经提到一个简单的指针相等测试(用于is)是快速的?

该钩子还可以使自定义类型声明自己等于None

1
2
3
class Devious(object):
    def __eq__(self, other):
        return other is None

现在你的x == None检验是正确的,即使x实际上不是None而是Devious的一个实例。如果你真的想知道x是否设置为None,那么只有x is None才能检测到这种情况。

None不是唯一可以用来测试身份的对象。当需要知道给定名称是否引用特定对象而不是值时,应该使用is

例如,有时需要允许None为有效值,但要检测是否没有指定值。通常,您可以使用None作为哨兵来检测是否遗漏了一个论点:

1
2
3
def foo(arg1, optional=None):
    if optional is None:
        # no value given for optional

但是如果您希望None是一个有效值,那么您将使用另一个sentinel:

1
2
3
4
5
_sentinel = object()

def foo(arg1, optional=_sentinel):
    if optional is _sentinel:
        # no value given for optional

现在您可以使用foo(1, None),它将被正确地视为一个值。