Python “==”和“是”之间有区别吗?

Python “==”和“是”之间有区别吗?,python,reference,equality,semantics,Python,Reference,Equality,Semantics,我的工作让我失望 在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 'Y

我的工作让我失望

在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确定它们是否是完全相同的对象

这是身份测试 ==相等性测试

每个小整数值都映射到一个值,因此每3个值都相同且相等。这是一个实现细节,不是语言规范的一部分,但是如果两个变量指向同一个对象,==如果变量引用的对象相等,

将返回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检查对象标识,而==检查相等性这一概念取决于两个操作数的类型

这只是一个幸运的巧合,它似乎能正确处理小整数,例如5==4+1。那是因为。这种行为完全依赖于实现,不能保证在所有形式的小型转换操作下都能保持

例如,Python 3.5也将短字符串设置为单例,但对它们进行切片会破坏此行为:

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

看看堆栈溢出问题


它主要归结为检查它们是否是相同的对象,而不仅仅是彼此相等。256以下的数字是一个特例。

有一个简单的经验法则告诉您何时使用==或is

==表示值相等。当您想知道两个对象是否具有相同的值时,请使用它。 是供参考之用。如果您想知道两个引用是否引用同一个对象,请使用它。 通常,当您将某个内容与简单类型进行比较时,通常会检查值是否相等,因此应该使用==。例如,您的示例的目的可能是检查x是否具有等于2==的值,而不是x是否字面上指的是与2相同的对象

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

>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False
这正是我们所期望的:a和b具有相同的值,但是不同的实体。但是这个呢

>>> 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

这是另一个不使用的明显原因:当您错误地使用它来实现值相等时,行为由实现决定。

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

NoneType只有一个实例,即None是单例。因此,foo==None和foo都不是同一意思。然而,is测试速度更快,Python的约定是使用foo is None

如果您正在做一些内省,或者在垃圾收集方面胡闹,或者检查您定制的字符串interning小工具是否正常工作,那么您可能有一个foo is bar的用例

True和False现在也是单例,但是没有foo==True的用例,也没有foo为True的用例

Python中的==和Is之间有区别吗? 是的,它们有一个非常重要的区别

>>> 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
==:检查相等性-语义是不一定是同一对象的等效对象将被测试为相等。作为:

运算符,==,>=,is和==,之间的区别是什么? ==和是不同的比较!正如其他人已经说过的那样:

==比较对象的值。 比较对象的引用。 在Python中,名称指对象,例如,在本例中,value1和value2指存储值1000的int实例:

因为value2引用了相同的对象,因此==将给出True:

在下面的示例中,名称value1和value2引用不同的int实例,即使两者都存储 相同整数:

>>> value1 = 1000
>>> value2 = 1000
因为存储的是同一个整型值==将为真,所以它通常被称为值比较。但是,is将返回False,因为它们是不同的对象:

>>> value1 == value2
True
>>> value1 is value2
False
什么时候用哪个? 一般来说,这是一个更快的比较。这就是为什么CPython缓存或重用是某些对象(如小整数、某些字符串等)的更好术语。但这应该被视为实现细节,即使不太可能在没有警告的情况下在任何时候发生更改

只有在以下情况下,才应使用is:

要检查两个对象是否真的是同一个对象,而不仅仅是相同的值。一个例子是,如果使用单例对象作为常量

要将值与值进行比较。Python中的常量是:

没有一个 真实的1 错误1 未实施 省略 __调试__ 类,例如int为int或int为float 内置模块或第三方模块中可能有其他常量。例如,从NumPy模块 在其他任何情况下,都应该使用==检查是否相等

我可以自定义行为吗? ==还有一个方面在其他答案中没有提到:它是。这意味着可以使用该方法自定义其行为。例如:

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 _u实现,则_eq _u使用的是:

因此,如果您想要的不仅仅是自定义类的引用比较,那么实现_eq__;实际上非常重要

另一方面,您无法自定义is检查。如果您有相同的参考,它将始终进行比较

这些比较是否总是返回布尔值? 因为_ueq _uuu可以重新实现或重写,所以它不限于返回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检查将始终返回真或假

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

通常情况下,不应执行任何“是真”或“是假”检查,因为通常在将条件隐式转换为布尔值(例如在if语句中)的上下文中使用这些检查。因此,进行真正的比较,隐式布尔型转换比单纯的布尔型转换要做更多的工作,而且你只使用布尔型,而这并不被认为是pythonic

就像PEP8提到的:

不要使用==将布尔值与True或False进行比较


当这篇文章中的其他人详细回答这个问题时,==和之间的差异是用于比较对象或变量的,我将主要强调is和==之间的比较,因为字符串可以给出不同的结果,我将敦促程序员小心地使用它们

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

输出:

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

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

结论与分析:

使用时要仔细比较字符串。 因为是用来比较对象的,而且在Python3+中,每个变量(比如string)都解释为对象,所以让我们看看上面几段中发生了什么

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

但是


他们中的大多数人已经回答了这个问题。正如基于我的理解和实验而非文件来源的补充说明,该声明

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

以上答案应理解为:

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

。我是根据以下测试得出这个结论的:

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运算符可能看起来与equality运算符相同,但是 它们不一样

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

我将不得不反对您将常量与is进行比较的断言-指向布尔值的名称应使用布尔上下文进行检查-如if _udebug _;:或if not _udebug _;:。如果uuu debug uuu为True,则永远不应该这样做:或者如果uuu debug uuu==True:-此外,常量只是一个常量语义值,而不是单例
在这种情况下,预先检查is在语义上是不正确的。我要求您找到一个源来支持您的断言-我不认为您会找到一个。@AaronHall是什么让您认为常量不是单例的?请注意,只有None、True、False和____________________________________。但是他们都是单身汉。读-Ctrl-F并查找单词,更糟。-如果你在进行单元测试,你会在某些情况下使用@AaronHall,你真的需要检查is-True或If-False,但是是的,这是非常罕见的-但是如果你做了,你可以使用is来做。这就是为什么即使是CPython有时也会使用它们,例如,或者为什么is-True比==True更糟糕?真的真的会失败吗?如果anything==True更可能失败,因为_eq_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,虽然它没有为“hello sam”执行缓存,因为它相对大于“hello”,即它管理“hello sam”字符串的不同引用,这就是为什么在后面的示例中“is”运算符返回false,如果我是,请更正我wrong@AkashGupta很抱歉延迟回复。我只是在Python解释器中添加了一些解释,解释为什么会发生这种情况。我希望这会有帮助。我发现:echo'import sys;tt=sys.argv[1];printtt是foo,tt==foo,idtt==idfoo'| python3-foo输出:False-True-False。您丢失了b=a[:]切片操作符列表复制部分,因此我编辑了您的答案,以便在那里发表评论。看起来我刚刚达到了一个临界点,在我的编辑应用之前不需要审查,所以希望这对你来说很酷。不管怎样,这里有一个关于如何复制我遇到的列表的有用参考,我必须参考这些列表来了解你在做什么:另一种证明差异的方法是比较不同类型的对象,当然,它们永远不会是同一个对象,但在使用==时仍然比较相等。例如,5.0是一个浮点值,而5是一个整数。但是5.0==5仍将返回True,因为它们表示相同的值。在性能和duck类型方面,解释程序总是通过比较操作数的内存地址来测试is,with==由对象决定是否将自身定义为等于其他内容。1000是10**3在Python 3.7中计算为True,因为10**3是int类型。但是1000是1e3,因为1e3是float类型。@AhmedFasih 1000是否是10**3是True取决于实现,并取决于编译器预计算表达式10**3。x=10;1000是x**3,计算结果为False。请仅对从其他来源引用的文本使用块引号,此时必须包含属性,请参见。如果这是您自己的文本,请删除块引号。关于a=500和b=500的第一个示例,只想指出,如果将a和b设置为介于[-5256]之间的整数,a is b实际上返回True。这里的更多信息:@AsheKetchum,是的,请注意,我写的Python的参考实现将-5..256范围内的整数对象缓存为单实例,这是出于性能原因。就像在这里添加我的两个位一样。如果你想检查它是否是同一个对象,比如说你有一个城市和路线对象的列表;你可以比较不同的地点,或者只是检查一下它是否在同一个城市——这里比较强的地方也是如此。否则,如果只关心原语,通常==就足够了。这更像是一条拇指规则,当事情变得艰难时,它会被违反。根本不使用也是一条好规则。惯用的说法是“无”是一个例外,但也就是说==None也有效…@Jean-Françoisfare另一个例外:似乎建议使用is来比较枚举。这意味着两个自定义类比较,比如a=Carnew,B=Carnew,如果我们使用a==B,这等于a是B,对吗?@UniSize我认为你是不对的。问题:1。你说a,B,但是你说a==B小写,Python是区分大小写的。2.你没有说a和b是否应该是等价的,但两个具有相同参数的实例暗示它们是等价的,但不是相同的对象,因此你的解释是错误的。请在这里重读我的答案,让我知道遗漏了什么,并且在回答时要小心和明确。@AaronHall我的道歉,首先,这是一个打字错误。我修正了它,a=Carnew,b=Carnew,如果我们用a=b,这等于a是b吗?我知道is是在检查两个对象是否在同一个内存位置,a==b是两个对象之间的比较。根据测试,a==b返回false,a也是b返回false。使用相同的初始化,为什么a==b返回false?
>>> MyClass(10) == MyClass(10)
__eq__ method called
True
class AClass(object):
    def __init__(self, value):
        self._value = value

>>> a = AClass(10)
>>> b = AClass(10)
>>> a == b
False
>>> a == a
>>> import numpy as np
>>> np.arange(10) == 2
array([False, False,  True, False, False, False, False, False, False, False], dtype=bool)
Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:
str = 'hello'
if (str is 'hello'):
    print ('str is hello')
if (str == 'hello'):
    print ('str == hello')
str is hello
str == hello
str2 = 'hello sam'
    if (str2 is 'hello sam'):
        print ('str2 is hello sam')
    if (str2 == 'hello sam'):
        print ('str2 == hello sam')
str2 == hello sam
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)
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 
>>> 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.