关于python:在”==”和”is”之间有区别吗?

Is there a difference between “==” and “is”?

我的google fu失败了。

在python中,以下两个相等的测试是等价的吗?

1
2
3
4
5
6
7
8
n = 5
# Test one.
if n == 5:
    print 'Yay!'

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

对于您要比较实例的对象(比如list),这是否成立?

好吧,这样回答我的问题:

1
2
3
4
5
6
7
8
9
L = []
L.append(1)
if L == [1]:
    print 'Yay!'
# Holds true, but...

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

那么,==测试值,其中is测试看它们是否是同一个对象?


(P)如果两个变量指向同一个目标,EDOCX1就是英文的,如果变量提到的目标是平等的,那么EDOCX1就是英文的。(p)字母名称(P)In your case,the second test only works because python caches small integer objects,which is an implementation detail.For larger integers,this does not work:(p)字母名称(P)The same holds true for string literals:(p)字母名称(P)请参看这个问题是好的。(p)


(P)有一个简单的规则thumb告诉你当你使用字母名称0或字母名称1。(p)

  • EDOCX1是为了价值平等。如果两个目标都有同样的价值,请使用它。
  • EDOCX1:Is for Reference Equality.使用它,当你想知道,如果两个参照系指相同的目标。

(P)总的来说,当你把一些东西与一个简单的类型进行比较时,你通常会检查价值平等,所以你应该使用字母名称0。For example,the intention of your example is probably to check whether x has a value equal to 2(EDOCX1 genital 0 nabic),not whether EDOCX1 individual 21 is literally referring to the same object as 2.(p)(P)Something else to note:because of the way the CPYTHON reference implementation works,you'll get unexpected and inconsistent results if you mistakenly use EDOCX1 pensible 1 to compare for reference equality on integers:(p)字母名称(P)That's pretty much what we expected:EDOCX1 plographic 23 welcx1 and EDOCX1 nable 24 have the same value,but are distinct entities.但这是怎么回事?(p)字母名称(P)这与早期结果不一致。这是怎么回事?It turns out the reference implementation of pyton caches integer objects in the range-5..这是一个例子,证明:(p)字母名称(P)1 This is another obvious reason not to use EDOCX1 plus 1:The behavior is left up to implementations when you're terrneous using it for value equality.(p)


(P)EDOCX1 Emoriones if the values are equal,while EDOCX1 original 1.Determines if they are the exact same object and equal.(p)


Is there a difference between == and is in Python?

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

==:检查是否相等——语义是等价对象(不一定是同一对象)将测试为相等。如文件所述:

The operators <, >, ==, >=, <=, and != compare the values of two objects.

is:检查身份-语义是对象(在内存中保存)是对象。文件中再次提到:

The operators is and is not test for object identity: x is y is true
if and only if x and y are the same object. Object identity is
determined using the id() function. x is not y yields the inverse
truth value.

因此,对标识的检查与检查对象的ID是否相等相同。也就是说,

1
a is b

相同:

1
id(a) == id(b)

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

其他使用说明

您应该将这些比较用于它们的语义。用is检查身份,用==检查是否相等。

标准库的官方python风格指南PEP8还提到了两个is的用例:

Comparisons to singletons like None should always be done with is or
is not, never the equality operators.

Also, beware of writing if x when you really mean if x is not None --
e.g. when testing whether a variable or argument that defaults to None
was set to some other value. The other value might have a type (such
as a container) that could be false in a boolean context!

从同一性推断平等

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

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

The default behavior for equality comparison (== and !=) is based on
the identity of the objects. Hence, equality comparison of instances
with the same identity results in equality, and equality comparison of
instances with different identities results in inequality. A
motivation for this default behavior is the desire that all objects
should be reflexive (i.e. x is y implies x == y).

为了保持一致性,建议:

Equality comparison should be reflexive. In other words, identical
objects should compare equal:

x is y implies x == y

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

1
2
3
4
5
6
7
>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)

反义词也通常是正确的-如果一些东西测试不平等,你通常可以推断他们不是同一个对象。

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

例外

一个显著的例外是nan——它总是测试不等于自身:

1
2
3
4
5
6
7
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan           # !!!!!
False

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

但是如果你发现不止一个对象是等价的,它就不能代替相等。

请注意,比较列表和元组的相等性将假定对象的标识是相等的(因为这是一个快速检查)。如果逻辑不一致,这可能会产生矛盾-正如对nan所说:

1
2
3
4
>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True

警示故事:

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

注释者的代码依赖于这样一个事实:小整数(包括5到256)在Python中是单例的,而不是检查是否相等。

Wow, this can lead to some insidious bugs. I had some code that checked if a is b, which worked as I wanted because a and b are typically small numbers. The bug only happened today, after six months in production, because a and b were finally large enough to not be cached. – gwg

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

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

这是一个生产失败,可能在代码检查中被捕获,也可能在样式检查中被捕获。

我要强调的是:不要用is来比较整数。


(P)他们是完全不同的。EDOCX1 1 On 1 Scaks for Object Identity,while EDOCX1 universal 0 welcox1 checks for equality(a notion that depends on the two operations'types).(p)(P)It is only a lucky coincidence that"EDOCX1 university 1"seems to work correctly with small integers(E.G.5=-4+1).That is because cpython optimizes the storage of integers in the range(-5 to 256)by making them singlotons.这一行为是完全的执行——依赖和不保证在少数变革行动的所有方面得到保护。(p)(P)For example,Python 3.5 also make short strings singlots,but slicing them disrupts this behavior:(p)字母名称


is==有什么区别?

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

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

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

1
2
value1 = 1000
value2 = value1

enter image description here

因为value2指的是同一个对象,所以is==将给予True

1
2
3
4
>>> value1 == value2
True
>>> value1 is value2
True

在下面的示例中,名称value1value2表示不同的int实例,即使两个实例都存储相同的整数:

1
2
>>> value1 = 1000
>>> value2 = 1000

enter image description here

因为同一个值(整数)存储在==将是True中,所以常被称为"值比较"。但是,is将返回False,因为它们是不同的对象:

1
2
3
4
>>> value1 == value2
True
>>> value1 is value2
False

何时使用哪个?

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

只有在下列情况下,您才应使用is

  • 想检查两个对象是否真的是同一个对象(而不仅仅是同一个"值")。一个例子是,如果使用一个singleton对象作为常量。
  • 希望将值与python常量进行比较。python中的常量是:

    • None
    • True1
    • False1
    • NotImplemented
    • Ellipsis
    • __debug__
    • 类(例如int is intint is float)
    • 内置模块或第三方模块中可能还有其他常量。例如,来自numpy模块的np.ma.masked

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

我可以自定义行为吗?

其他答案中还没有提到EDOCX1[1]的某些方面:它是Python"数据模型"的一部分。这意味着它的行为可以使用__eq__方法进行定制。例如:

1
2
3
4
5
6
7
8
9
10
11
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)))

这只是一个人工的例子来说明这个方法实际上是被调用的:

1
2
3
>>> MyClass(10) == MyClass(10)
__eq__ method called
True

注意,默认情况下(如果在类或超类中找不到其他__eq__实现),__eq__使用is

1
2
3
4
5
6
7
8
9
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数组,==将返回一个数组:

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

is支票将始终返回TrueFalse

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

一般来说,您不应该执行任何is Trueis False检查,因为通常在将条件隐式转换为布尔值的上下文中使用这些"检查"(例如在if语句中)。因此,进行is True比较和隐式布尔值转换比仅仅进行布尔值转换要做更多的工作,而且你只需要局限于布尔值(这不被认为是Python)。

就像pep8提到的:

Don't compare boolean values to True or False using ==.

1
2
3
Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:


(P)https://docs.python.org/library/stdtypes.html;comparisons(p)(P)东经一EDOCX1语言平等测试0(p)(P)EACH(small)integer value is mapped to a single value,so every 3 is identical and equal.This is an implementation detail,not part of the language spec though(p)


(P)你的回答是正确的。The EDOCX1 commercial operator compars the identity of two objects.The EDOCX1 commercial 0 operator compars the values of two objects.(p)(P)An object's identity never changes once it has been created;you may think of it as the object's address in memory.(p)(P)You can control comparison behaviour of object values by defining a EDOCX1 universal method 9 or a rich comparison method like EDOCX1(p)


(P)有一种观点认为,Stack Overflow Question Python's"is"operator behaves unexpectedly with integers.(p)(P)What it mostly boils down to is that"EDOCX1 plography 1"welcomes to see if they are the same object,not just equal to each other(the numbers below 256 are a special case).(p)


==运算符比较两个操作数的值,并检查值是否相等。而is运算符检查两个操作数是否引用同一对象。

1
2
3
4
a = [1,2,3,4]
b = a
print(a == b) # true
print(a is b) # true

但是如果我们这样做

1
2
3
4
b = a[:] # b now references a copy of a
print(a == b) # true
print(a is b) # false
print(a is not b) # true

基本上,is可以被认为是id(a) == id(b)的缩写。然而,除此之外,还有运行时环境的一些怪癖使事情变得更加复杂。与is相比,短字符串和小整数将返回True,因为python机器试图为相同的对象使用较少的内存。

1
2
3
4
5
a = 'python'
b = 'python'

print(a == b) # true
print(a is b) # true

他们大多数人已经回答了这一点。正如附加说明(基于我的理解和实验,但不是来自文档来源),声明

== if the objects referred to by the variables are equal

以上答案应理解为

== if the objects referred to by the variables are equal and objects belonging to the same type/class

. 我根据以下测试得出结论:

1
2
3
4
5
6
7
8
9
10
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检查两个引用是否指向同一对象。==检查两个对象是否具有相同的值。

1
2
3
4
5
6
7
8
9
10
11
12
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

正如约翰·费米内拉所说,大多数时候你会使用==和!=因为您的目标是比较值。我只想把剩下的时间你会做什么分类:

非类型的实例只有一个,也就是说,none是单实例。因此,foo == Nonefoo is None的含义相同。然而,is测试速度更快,而pythonic约定使用foo is None

如果您正在对垃圾收集进行一些反省或弄脏,或者检查您定制的字符串截取工具是否正常工作,那么您可能有一个用于foo的用例是bar

正确和错误也是(现在)单一的,但是没有用于foo == True的用例,也没有用于foo is True的用例。


正如本篇文章中其他人详细回答这个问题一样,我将着重比较is==对于可以给出不同结果的字符串,并敦促程序员仔细使用它们。

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

1
2
3
4
5
str = 'hello'
if (str is 'hello'):
    print ('str is hello')
if (str == 'hello'):
    print ('str == hello')

出:

1
2
str is hello
str == hello

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

1
2
3
4
5
str = 'hello sam'
    if (str is 'hello sam'):
        print ('str is hello sam')
    if (str == 'hello sam'):
        print ('str == hello sam')

出:

1
str == hello sam

结论:

仔细使用is比较字符串


事实上,我想添加这个评论,但不能很容易地美化它,因此添加作为一个答案,请不要认为这是一个答案。

这就是我所做的理解--

execute following one by one and understand output on every step

1
2
3
4
5
6
7
a = [1,2]
b = [1,2,3]
b.pop()
id(a)
id(b)
a is b
a == b

is和equals之间的python差异(==)

The is operator may seem like the same as the equality operator but
they are not same.

The is checks if both the variables point to the same object whereas
the == sign checks if the values for the two variables are the same.

So if the is operator returns True then the equality is definitely
True, but the opposite may or may not be True.

下面是一个例子来说明相似性和差异。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> 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
1
Tip: Avoid using is operator for immutable types such as strings and numbers, the result is unpredictable.


"=="比较值

"is"比较基础对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# this pgm is to show you the diff b/n == and is

# a==b and a is b

# == compares values
# is compares references i.e compares wether two variables refer to same object(memory)

a=10
b=10
print(a==b) # returns True as a,b have same value 10
print(a is b)
# returns True,
# we usually falsey assume that a =10 a new object . b=10 a new obj created
# but actually when b=10 ,nothing but b is pointed to 10 until value of a or b is changed from 10

a=[1]
b=[1]
print(a==b)
#returns True as a,b have a list element 1
print(a is b)
#returns False because here two different objs are created when initiated with lists

o1是o2=>比较o1和o2是否都指向内存中相同的物理位置(换句话说,如果它们是相同的对象)

o1==o2=>这里python调用o1的uuu cmp uuu(o2)方法,理想情况下,该方法应该比较值并返回true或false。(换句话说,它比较值)

对于爪哇人来说:

  • 在Java中,以确定两个字符串变量是否引用相同的字符串变量。使用str1==str2的物理内存位置。(被称为对象)标识,它是用python编写的,因为str1是str2)。

  • 比较Java中的字符串值,UsReST1.0(Str2);在Python中,使用str1==str2。

例子:

1
2
3
4
5
6
7
8
9
class A():
    ...:     def __init__(self,a):
    ...:         self.a = a
    ...:     def __repr__(self):
    ...:         return str(self.a)
    ...:     def __cmp__(self, value):
    ...:         print self.a
    ...:         print value.a
    ...:         return cmp(self.a, value.a)

python shell输出:

o = A(2)
o1 = o

o == o1
2
2
True

o is o1
True

o1 = A(2)

o is o1
False


是的,两者都有区别。

  • "==":按值比较对象。
  • "in":按引用比较对象。

    1
    2
    3
    4
    5
    6
    7
    a = [1,2,3]  
    b = a # both pointing to same object (memory location)

    a == b:  
    True  
    a in b:  
    True  #because a and b are pointing to same object

现在让我们考虑一下这个例子:

1
2
3
4
5
6
7
a = [1,2,3]
b = list(a)  # creating copy of object a

a == b:  
True  # as values are same
a in b:  
False  # because they are pointing to different object.


虽然所有这些依赖于异议指针比较与值比较的实现的答案可能都是正确的,但使用is来确定变量值是否为None(在布尔逻辑中,通常表示为NULL)有更深层的语法原因。

在关系数据库和其他逻辑系统中,NULL表示实际值"未知"。因此,逻辑表达式xx == NULL必须始终对NULL本身进行计算,因为不可能知道xx是否与未知值相同,无论它有什么值。在更严格地遵循布尔逻辑规则的编程语言中,xx == NULL或pytholy xx == None正确地评估为NULL,并且必须提供可选的方法来确定变量值是否为NULL。在这方面,由于对象引用None的单一性,python是一个离群值。但为了清晰和逻辑正确,在我看来,使用python is比较运算符更为合理。