我的Google-fu让我失望了

在Python中,以下两个相等测试是否等效?

n = 5
# Test one.
if n == 5:
    print 'Yay!'

# Test two.
if n is 5:
    print 'Yay!'

这是否适用于对象,你将比较实例(一个列表说)?

这就回答了我的问题

L = []
L.append(1)
if L == [1]:
    print 'Yay!'
# Holds true, but...

if L is [1]:
    print 'Yay!'
# Doesn't.

所以==测试值测试是看他们是否相同的对象?


当前回答

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

什么时候用哪个?

一般来说,这是一个更快的比较。这就是为什么CPython缓存(或者重用可能是更好的术语)某些对象,如小整数,一些字符串等。但这应该被视为实现细节,可以(即使不太可能)在任何时候毫无警告地更改。

你应该只在以下情况下使用is:

想要检查两个对象是否真的是同一个对象(而不仅仅是相同的“值”)。例如,如果您使用单例对象作为常量。 想要将值与Python常量进行比较。Python中的常量是: 没有一个 True1 False1 NotImplemented 省略 __debug__ 类(例如int是int或int是float) 在内置模块或第三方模块中可以有额外的常量。例如NumPy模块中的np.ma.mask)

在其他情况下,您应该使用==来检查是否相等。

我可以自定义行为吗?

==的某些方面在其他答案中没有提到:它是python“数据模型”的一部分。这意味着它的行为可以使用__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__使用的是:

class AClass(object):
    def __init__(self, value):
        self._value = value

>>> a = AClass(10)
>>> b = AClass(10)
>>> a == b
False
>>> a == a

因此,如果你想要自定义类的引用比较之外的“更多”,实现__eq__实际上是很重要的!

另一方面,您不能自定义支票。如果你有相同的引用,它总是会比较。

这些比较是否总是返回布尔值?

因为__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!


正如Aaron Hall在评论中提到的:

一般来说,你不应该做任何is True或is False检查,因为人们通常在隐式将条件转换为布尔值的上下文中使用这些“检查”(例如在if语句中)。因此,进行is True比较和隐式布尔类型强制转换比仅仅进行布尔类型强制转换要做更多的工作——并且您将自己限制在布尔类型(这被认为不是python类型)。

就像PEP8提到的:

不要用==将布尔值与True或False进行比较。 是:如果问候语: No: if greeting == True: 更糟:如果问候是真的:

其他回答

看看Stack Overflow问题Python的“is”运算符对整数的行为出人意料。

它主要归结为“is”检查它们是否是相同的对象,而不仅仅是彼此相等(256以下的数字是一个特殊情况)。

他们中的大多数人已经回答到点子上了。只是作为一个额外的说明(基于我的理解和实验,但不是来自文档来源),声明

如果变量引用的对象相等,则==

从以上答案应读为

如果变量引用的对象相等且属于相同类型/类的对象==

. 我根据下面的测试得出了这个结论:

list1 = [1,2,3,4]
tuple1 = (1,2,3,4)

print(list1)
print(tuple1)
print(id(list1))
print(id(tuple1))

print(list1 == tuple1)
print(list1 is tuple1)

这里,列表和元组的内容是相同的,但类型/类是不同的。

它们完全不同。Is检查对象的同一性,而==检查相等性(这一概念取决于两个操作数的类型)。

这只是一个幸运的巧合,“is”似乎正确地适用于小整数(例如5 == 4+1)。这是因为CPython通过使整数为单例来优化范围(-5到256)内的整数的存储。这种行为完全依赖于实现,并且不能保证在所有形式的小型转换操作下都能保留。

例如,Python 3.5也创建了短字符串单例,但将它们切片会破坏这种行为:

>>> "foo" + "bar" == "foobar"
True
>>> "foo" + "bar" is "foobar"
True
>>> "foo"[:] + "bar" == "foobar"
True
>>> "foo"[:] + "bar" is "foobar"
False

简而言之,is检查两个引用是否指向同一个对象。==检查两个对象是否具有相同的值。

a=[1,2,3]
b=a        #a and b point to the same object
c=list(a)  #c points to different object 

if a==b:
    print('#')   #output:#
if a is b:
    print('##')  #output:## 
if a==c:
    print('###') #output:## 
if a is c:
    print('####') #no output as c and a point to different object 

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

什么时候用哪个?

一般来说,这是一个更快的比较。这就是为什么CPython缓存(或者重用可能是更好的术语)某些对象,如小整数,一些字符串等。但这应该被视为实现细节,可以(即使不太可能)在任何时候毫无警告地更改。

你应该只在以下情况下使用is:

想要检查两个对象是否真的是同一个对象(而不仅仅是相同的“值”)。例如,如果您使用单例对象作为常量。 想要将值与Python常量进行比较。Python中的常量是: 没有一个 True1 False1 NotImplemented 省略 __debug__ 类(例如int是int或int是float) 在内置模块或第三方模块中可以有额外的常量。例如NumPy模块中的np.ma.mask)

在其他情况下,您应该使用==来检查是否相等。

我可以自定义行为吗?

==的某些方面在其他答案中没有提到:它是python“数据模型”的一部分。这意味着它的行为可以使用__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__使用的是:

class AClass(object):
    def __init__(self, value):
        self._value = value

>>> a = AClass(10)
>>> b = AClass(10)
>>> a == b
False
>>> a == a

因此,如果你想要自定义类的引用比较之外的“更多”,实现__eq__实际上是很重要的!

另一方面,您不能自定义支票。如果你有相同的引用,它总是会比较。

这些比较是否总是返回布尔值?

因为__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!


正如Aaron Hall在评论中提到的:

一般来说,你不应该做任何is True或is False检查,因为人们通常在隐式将条件转换为布尔值的上下文中使用这些“检查”(例如在if语句中)。因此,进行is True比较和隐式布尔类型强制转换比仅仅进行布尔类型强制转换要做更多的工作——并且您将自己限制在布尔类型(这被认为不是python类型)。

就像PEP8提到的:

不要用==将布尔值与True或False进行比较。 是:如果问候语: No: if greeting == True: 更糟:如果问候是真的: