当前位置:  开发笔记 > 编程语言 > 正文

"=="和"是"之间有区别吗?

如何解决《"=="和"是"之间有区别吗?》经验,为你挑选了8个好方法。

我的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是否是同一个对象?



1> Torsten Mare..:

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

请同时查看此问题.


我发现:`echo'import sys; tt = sys.argv [1]; print(tt是“ foo”,tt ==“ foo”,id(tt)== id(“ foo”))'|| python3-foo`输出:`False True False`。

2> John Feminel..:

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

==是为了价值平等.当您想知道两个对象是否具有相同值时,请使用它.

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

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



3> stephenbayer..:

==确定值是否相等,同时is确定它们是否完全相同且相等.



4> Aaron Hall..:

Python ==isPython 之间有区别吗?

是的,他们有非常重要的区别.

==:检查是否相等 - 语义是等效对象(不一定是同一个对象)将测试相等.正如文件所说:

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

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

对象标识的运算符isis not测试:x is y当且仅当xy是同一个对象时才是真的.使用该id()函数确定对象标识.x is not y产生反向真值.

因此,检查身份与检查对象的ID是否相等是一样的.那是,

a is b

是相同的:

id(a) == id(b)

哪个id是内置函数,它返回一个"保证在同时存在的对象中是唯一的"整数(参见参考资料help(id))以及任何对象的位置ab位置.

其他使用说明

您应该使用这些比较来表示它们的语义.使用is检查身份和==检查平等.

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

与单身人士的比较None应始终使用is或者 is not从不使用相等运算符.

此外,if x当你真正想要时要小心写作if x is not None- 例如,在测试默认的变量或参数是否None 设置为其他值时.另一个值可能有一个类型(如容器)在布尔上下文中可能为false!

从身份中推断平等

如果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中的单例,而不是检查相等性.

哇,这可能导致一些阴险的错误.我有一些代码检查a是否是b,这是我想要的,因为a和b通常是小数字.这个错误只发生在今天,经过六个月的生产,因为a和b最终足够大,不能被缓存. - gwg

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

它在生产中起作用 - 直到代码检查大于256的整数,此时它在生产中失败.

这是一个生产故障,可能在代码审查中或可能与样式检查器中发生.

我要强调:不要is用来比较整数.



5> Dan Lenski..:

它们完全不同. 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



6> MSeifert..:
is和之间有什么区别==

==is不同的比较!正如其他人已经说过:

== 比较对象的值.

is 比较对象的引用.

在Python中,名称引用对象,例如在这种情况下,value1value2引用int存储值的实例1000:

value1 = 1000
value2 = value1

在此输入图像描述

因为value2指的是同一个对象is,==会给出True:

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

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

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

在此输入图像描述

因为(整数)存储相同的值==将是True,这就是为什么它通常被称为"值比较".但是is会返回,False因为这些是不同的对象:

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

什么时候用哪个?

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

你应该is在你:

想检查两个对象是否真的是同一个对象(不只是相同的"值").一个例子可以是,如果使用一个单独的对象为常数.

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

None

True1

False1

NotImplemented

Ellipsis

__debug__

类(例如int is intint is float)

内置模块或第三方模块中可能存在其他常量.例如np.ma.masked来自NumPy模块)

其他每种情况下,您都应该使用它==来检查是否相等.

我可以自定义行为吗?

==在其他答案中已经有一些方面尚未提及:它是Pythons"数据模型"的一部分.这意味着可以使用该__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!


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

通常,您不应该执行任何操作is Trueis False检查,因为通常在上下文中使用这些"检查",隐式地将条件转换为布尔值(例如在if语句中).因此,进行is True比较隐式布尔强制转换比仅仅进行布尔强制转换更多的工作 - 并且您将自己限制为布尔值(不被认为是pythonic).

像PEP8一样提到:

不要将布尔值与之比较TrueFalse使用==.

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



7> 小智..:

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

is测试==相等的身份 测试

每个(小)整数值都映射到一个值,因此每3个相同且相等.这是一个实现细节,但不是语言规范的一部分



8> Dave Webb..:

你的答案是对的.该is运算符比较两个对象的身份.该==操作比较两个对象的值.

对象的标识一旦创建就永远不会改变; 您可能会将其视为内存中对象的地址.

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

推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有