"=="和“女儿家吗?

我的Google-fu让我很失望。

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

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


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

这是否适用于对象,你将比较实例(list说)?

这就回答了我的问题

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


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

所以==测试值,而is测试是否它们是同一个对象?

476845 次浏览

==确定两个值是否相等,而is确定它们是否完全相同。

https://docs.python.org/library/stdtypes.html#comparisons

is测试身份 ==测试是否相等

每一个(小的)整数值都被映射到一个单独的值,所以每3都是相同的。这是一个实现细节,但不是语言规范的一部分

如果两个变量指向同一个对象(在内存中),is将返回True,如果变量引用的对象相等,则返回==

>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
>>> b == a
True


# Make a new copy of list `a` via the slice operator,
# and assign it to variable `b`
>>> b = a[:]
>>> b is a
False
>>> b == a
True

在您的情况下,第二个测试只能工作,因为Python缓存小整数对象,这是一个实现细节。对于较大的整数,这行不通:

>>> 1000 is 10**3
False
>>> 1000 == 10**3
True

这同样适用于字符串字面量:

>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True

请参阅这个问题

你的答案是正确的。is操作符比较两个对象的标识。==操作符比较两个对象的值。

对象的标识一旦创建就不会改变;你可以把它看作是对象在内存中的地址。

您可以通过定义__cmp__方法或丰富的比较方法(如__eq__)来控制对象值的比较行为。

他们是完全不同的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

  • ==代表价值平等。当你想知道两个对象是否有相同的值时使用它。
  • is代表参考平等。当您想知道两个引用是否指向同一个对象时,可以使用它。

一般来说,当你比较一个简单类型时,你通常会检查价值平等,所以你应该使用==。例如,您的示例的目的可能是检查x是否有一个等于2的值(==),而不是x是否字面上引用与2相同的对象。


另外需要注意的是:由于CPython引用实现的工作方式,如果你错误地使用is来比较整数上的引用是否相等,你会得到意想不到的不一致的结果:

>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False

这正是我们所期望的:ab具有相同的值,但它们是不同的实体。但是这个呢?

>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True

这与先前的结果不一致。这是怎么回事?事实证明,Python的参考实现缓存范围为-5..出于性能考虑,将256作为单例实例。下面是一个例子:

>>> for i in range(250, 260): a = i; print "%i: %s" % (i, a is int(str(i)));
...
250: True
251: True
252: True
253: True
254: True
255: True
256: True
257: False
258: False
259: False

这是不使用is的另一个明显原因:当您错误地将其用于值相等时,该行为将留给实现。

正如John Feminella所说,大多数情况下您将使用==和!=,因为您的目标是比较值。我只是想把剩下的时间里你会做的事情分类:

有且只有一个实例的NoneType,即None是一个单例。因此,foo == Nonefoo is None的意思相同。然而,is测试更快,并且python惯例是使用foo is None

如果您正在进行一些自省或垃圾收集,或检查您定制的字符串实习小工具是否工作或诸如此类,那么foo的用例可能是bar

True和False(现在)也是单例,但是没有foo == Truefoo is True的用例。

在Python中==is之间有区别吗?

是的,它们有一个非常重要的区别。

==:检查是否相等——语义是等价的对象(不一定是同一个对象)将被测试为相等。作为文档中说的一样:

运算符<, >, ==, >=, <=和!=比较两个对象的值。

is:检查身份-语义是对象(在内存中)对象。再次,文档中说的一样:

运算符isis not测试对象身份:x is y为真 当且仅当xy是同一个对象。对象恒等式是 使用id()函数确定。x is not y产生相反的结果 真值。< / p >

因此,检查标识符与检查对象的id是否相等是一样的。也就是说,

a is b

等于:

id(a) == id(b)

其中id是一个内建函数,返回一个“在同时存在的对象中保证唯一”的整数(参见help(id)),其中ab是任意对象。

其他使用说明

您应该使用这些语义比较。使用is检查身份,使用==检查是否相等。

所以一般来说,我们使用is来检查标识。当我们检查一个在内存中只存在一次的对象时,这通常是有用的,在文档中称为“单例”。

is的用例包括:

  • # EYZ0
  • enum值(当使用enum模块中的Enums时)
  • 通常模块
  • 通常是类定义产生的类对象
  • 通常是由函数定义产生的函数对象
  • 任何其他在内存中只存在一次的对象(通常都是单例对象)
  • 一个你想要的特定对象

==的常用用例包括:

  • 数字,包括整数
  • 字符串
  • 列表
  • 字典
  • 自定义可变对象
  • 其他内建的不可变对象,在大多数情况下

同样,对于==,一般的用例是您想要的对象可能不是相同对象,而是等效对象

PEP 8说明

标准库的官方Python风格指南PEP 8也提到了is的两个用例:

None这样的单例对象的比较应该始终使用is

. is not,绝不是相等操作符 此外,当你真正想说的是if x is not None——时,要注意写if x 例如,当测试一个变量或参数是否默认为None时 被设置为其他值。另一个值可能具有类型(例如 作为容器),在布尔上下文中可能是假的!< / p >

由同一推断相等

如果is为真,则可以推断出通常的相等性——从逻辑上讲,如果一个对象是自身,那么它应该测试为等效于自身。

在大多数情况下,这个逻辑是正确的,但它依赖于__eq__特殊方法的实现。正如文档所说,

相等性比较的默认行为(==!=)是基于 对象的身份。因此,实例的相等性比较 具有相同的同一性结果就等于相等,而相等的比较 具有不同身份的实例会导致不平等。一个 这种默认行为的动机是所有对象的愿望 应该是自反的(即x是y暗示x == y)。

为了保持一致性,建议:

平等比较应该是自反的。换句话说,完全相同 对象的比较应该等于:

x is y意味着x == y

我们可以看到这是自定义对象的默认行为:

>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)

反证法通常也是正确的——如果某物测试为不相等,你通常可以推断出它们不是同一个物体。

由于相等性测试可以自定义,因此这种推断并不总是适用于所有类型。

一个例外

一个值得注意的例外是nan -它总是被测试为不等于自身:

>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan           # !!!!!
False

检查身份比检查相等性要快得多(相等性可能需要递归地检查成员)。

但它不能代替相等,因为你可能会发现多个对象是相等的。

注意,比较列表和元组的相等性将假定对象的身份相等(因为这是一个快速检查)。如果逻辑不一致,就会产生矛盾——就像nan:

>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True

一个警世故事:

问题是试图使用is来比较整数。您不应该假定一个整数的实例与另一个引用获得的实例是相同的实例。下面这个故事解释了原因。

一位评论者的代码依赖于小整数(-5到256)在Python中是单例,而不是检查是否相等。

哇,这可能会导致一些潜伏的bug。我写了一些代码来检查a是不是b,这就像我想要的那样,因为a和b通常都是很小的数字。这个错误直到今天才出现,因为a和b终于大到不能被缓存了。——gwg

它在开发过程中发挥了作用。它可能通过了一些单元测试。

它在生产中工作-直到代码检查大于256的整数,在这一点上它在生产中失败了。

这是一个生产失败,可以在代码检查或样式检查器中发现。

让我强调一下:不使用is来比较整数

is==有什么区别?

==is是不同的比较!正如其他人所说:

  • ==比较对象的值。
  • is比较对象的引用。

在Python中,名称指的是对象,例如在本例中value1value2指的是存储值1000int实例:

value1 = 1000
value2 = value1

enter image description here

因为value2指向同一个对象is==将给出True:

>>> value1 == value2
True
>>> value1 is value2
True

在下面的例子中,名称value1value2指的是不同的int实例,即使它们存储的是相同的整数:

>>> value1 = 1000
>>> value2 = 1000

enter image description here

因为存储相同的值(整数)==将是True,这就是为什么它经常被称为“值比较”。但是is将返回False,因为它们是不同的对象:

>>> value1 == value2
True
>>> value1 is value2
False

什么时候用哪个?

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

你应该只使用is,如果你:

  • 想检查两个对象是否真的是同一个对象(而不仅仅是相同的"value")。例如,如果使用一个单例对象作为常量。

  • 想将一个值与Python < em >常数< / em >进行比较。Python中的常量是:

    • # EYZ0
    • # EYZ0 # EYZ1
    • # EYZ0 # EYZ1
    • # EYZ0
    • # EYZ0
    • # EYZ0
    • 类(例如int is intint is float)
    • 在内置模块或第三方模块中可以有额外的常量。例如NumPy模块中的np.ma.masked)

每隔一段时间你就应该使用==中检查是否相等。

我可以自定义行为吗?

==的一些方面在其他答案中没有提到:它是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__使用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__可以被重新实现或重写,所以它不局限于返回TrueFalse。它可以返回任何东西(但在大多数情况下它应该返回一个布尔值!)

例如,对于NumPy数组,==将返回一个数组:

>>> import numpy as np
>>> np.arange(10) == 2
array([False, False,  True, False, False, False, False, False, False, False], dtype=bool)

但是is检查将总是返回TrueFalse!


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

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

就像PEP8提到的:

不要用==将布尔值与TrueFalse进行比较。

Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:

因为这篇文章中的其他人详细回答了==is在比较对象或变量方面的差异,我认为强调主要是is== 为字符串之间的比较,它们可以给出不同的结果,我希望程序员仔细使用它们。

对于字符串比较,请确保使用==而不是is:

str = 'hello'
if (str is 'hello'):
print ('str is hello')
if (str == 'hello'):
print ('str == hello')

:

str is hello
str == hello

在下面的例子中,==is将得到不同的结果:

str2 = 'hello sam'
if (str2 is 'hello sam'):
print ('str2 is hello sam')
if (str2 == 'hello sam'):
print ('str2 == hello sam')

:

str2 == hello sam

结论与分析:

使用is仔细比较字符串。 由于is用于比较对象,并且在Python 3+中,每个变量(如string)都被解释为对象,让我们看看上面段落中发生了什么

在python中,有一个id函数,它显示一个对象在其生命周期内的唯一常数。这个id在Python解释器的后端使用is关键字来比较两个对象。

str = 'hello'
id('hello')
> 140039832615152
id(str)
> 140039832615152

str2 = 'hello sam'
id('hello sam')
> 140039832615536
id(str2)
> 140039832615792

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

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

从以上答案应读为

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

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

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检查两个引用是否指向同一个对象。==检查两个对象是否具有相同的值。

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和equals之间的Python差异(==)

is运算符可能看起来和相等运算符一样,但是

is检查两个变量是否指向同一个对象 ==符号检查两个变量的值是否相同 所以如果is操作符返回True,那么等式肯定是

.

.

.

.

.

这里有一个例子来说明相似点和不同点。

>>> a = b = [1,2,3]
>>> c = [1,2,3]
>>> a == b
True
>>> a == c
True
>>> a is b
True
>>> a is c
False
>>> a = [1,2,3]
>>> b = [1,2]
>>> a == b
False
>>> a is b
False
>>> del a[2]
>>> a == b
True
>>> a is b
False
Tip: Avoid using is operator for immutable types such as strings and numbers, the result is unpredictable.