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

Ber*_*ard 630 python equality reference semantics

我的Google-fu让我失望了.

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

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

# Test two.
if n is 5:
    print 'Yay!'
Run Code Online (Sandbox Code Playgroud)

对于您要比较实例的对象(list比如说),这是否适用?

好的,所以这样的答案我的问题:

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

if L is [1]:
    print 'Yay!'
# Doesn't.
Run Code Online (Sandbox Code Playgroud)

所以==测试值测试的地方is是否是同一个对象?

Tor*_*rek 868

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
Run Code Online (Sandbox Code Playgroud)

在您的情况下,第二个测试只有效,因为Python缓存小整数对象,这是一个实现细节.对于较大的整数,这不起作用:

>>> 1000 is 10**3
False
>>> 1000 == 10**3
True
Run Code Online (Sandbox Code Playgroud)

对于字符串文字也是如此:

>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True
Run Code Online (Sandbox Code Playgroud)

请同时查看此问题.

  • 在 Python 3.7 中,“1000 is 10**3”的计算结果为 True,因为 10**3 是“int”类型。但“1000 is 1e3”的计算结果为 False,因为 1e3 是“float”类型。 (6认同)
  • 只是一个旁注。Python 3.8 及更高版本在比较像 *1000 is 10\*\*3* 这样的文字时返回 SyntaxWarning:`SyntaxWarning: "is" 与文字。您的意思是“==”吗?` (4认同)
  • @AhmedFasih“1000 is 10**3”是否为真取决于实现,并且取决于编译器预评估表达式“10**3”。`x=10;1000 is x**3` 计算结果为 `False`。 (3认同)
  • 我发现:`echo'import sys; tt = sys.argv [1]; print(tt是“ foo”,tt ==“ foo”,id(tt)== id(“ foo”))'|| python3-foo`输出:`False True False`。 (2认同)

Joh*_*lla 294

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

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

通常,当您将某些内容与简单类型进行比较时,通常会检查值是否相等,因此您应该使用==.例如,您的示例的意图可能是检查x是否具有等于2(==)的值,而不是x字面上是否指向与2相同的对象.


还有一点要注意:由于CPython参考实现的工作方式,如果你错误地is用来比较整数上的引用相等性,你会得到意想不到的和不一致的结果:

>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False
Run Code Online (Sandbox Code Playgroud)

这几乎是我们的预期:a并且b具有相同的价值,但却是不同的实体.但是这个怎么样?

>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True
Run Code Online (Sandbox Code Playgroud)

这与之前的结果不一致.这里发生了什么?事实证明,由于性能原因,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
Run Code Online (Sandbox Code Playgroud)

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

  • 关于“a=500”和“b=500”的第一个示例,只是想指出,如果将“a”和“b”设置为 [-5, 256] 之间的整数,则“a 是 b” ` 实际上返回 `True`。更多信息请参见:/sf/ask/21441941/ (3认同)

ste*_*yer 33

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


Aar*_*all 26

Python ==isPython 之间有区别吗?

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

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

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

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

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

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

a is b
Run Code Online (Sandbox Code Playgroud)

是相同的:

id(a) == id(b)
Run Code Online (Sandbox Code Playgroud)

哪个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)
Run Code Online (Sandbox Code Playgroud)

相反的情况通常也是正确的 - 如果某些事情测试不相等,你通常可以推断它们不是同一个对象.

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

例外

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

>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan           # !!!!!
False
Run Code Online (Sandbox Code Playgroud)

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

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

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

>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True
Run Code Online (Sandbox Code Playgroud)

一个警示故事:

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

评论者的代码依赖于小整数(-5到256,包括)是Python中的单例,而不是检查相等性.

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

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

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

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

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


Dan*_*ski 19

它们完全不同. 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
Run Code Online (Sandbox Code Playgroud)


MSe*_*ert 19

is和之间有什么区别==

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

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

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

value1 = 1000
value2 = value1
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

>>> value1 == value2
True
>>> value1 is value2
True
Run Code Online (Sandbox Code Playgroud)

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

>>> value1 = 1000
>>> value2 = 1000
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

>>> value1 == value2
True
>>> value1 is value2
False
Run Code Online (Sandbox Code Playgroud)

什么时候用哪个?

通常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)))
Run Code Online (Sandbox Code Playgroud)

这只是一个人为的例子来说明该方法真的被称为:

>>> MyClass(10) == MyClass(10)
__eq__ method called
True
Run Code Online (Sandbox Code Playgroud)

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

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

>>> a = AClass(10)
>>> b = AClass(10)
>>> a == b
False
>>> a == a
Run Code Online (Sandbox Code Playgroud)

因此,__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)
Run Code Online (Sandbox Code Playgroud)

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:
Run Code Online (Sandbox Code Playgroud)

  • 我将不得不不同意您将“常量”与 `is` 进行比较的断言 - 应该使用布尔上下文检查指向布尔值的名称 - 例如 `if __debug__:` 或 `if not __debug__:`。你永远不应该做 `if __debug__ is True:` 或 `if __debug__ == True:` - 此外,常量只是一个常量语义值,而不是单例,因此在这种情况下用 `is` 检查在语义上是不正确的。我挑战你找到一个来源来支持你的断言——我认为你不会找到一个。 (2认同)

小智 10

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

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

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


Dav*_*ebb 6

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

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

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


cob*_*bal 5

看一下 Stack Overflow 问题Python\'s \xe2\x80\x9cis\xe2\x80\x9d 运算符对整数的行为异常

\n\n

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

\n


ima*_*bet 5

由于本文中的其他人详细回答了比较对象或变量之间的差异==和比较对象或变量的问题,我将主要强调可以给出不同结果的字符串之间的比较和字符串的比较,我会敦促程序员仔细使用它们。isis==

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

str = 'hello'
if (str is 'hello'):
    print ('str is hello')
if (str == 'hello'):
    print ('str == hello')
Run Code Online (Sandbox Code Playgroud)

出去:

str is hello
str == hello
Run Code Online (Sandbox Code Playgroud)

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

str2 = 'hello sam'
    if (str2 is 'hello sam'):
        print ('str2 is hello sam')
    if (str2 == 'hello sam'):
        print ('str2 == hello sam')
Run Code Online (Sandbox Code Playgroud)

出去:

str2 == hello sam
Run Code Online (Sandbox Code Playgroud)

结论与分析:

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

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

str = 'hello'
id('hello')
> 140039832615152
id(str)
> 140039832615152
Run Code Online (Sandbox Code Playgroud)

str2 = 'hello sam'
id('hello sam')
> 140039832615536
id(str2)
> 140039832615792
Run Code Online (Sandbox Code Playgroud)

  • 我使用的是 Python 3.9,并且 `str is 'hello'` 会抛出 `SyntaxWarning: "is" 和文字。你的意思是“==”吗?`这告诉我们需要使用`==`进行字符串比较,这很方便。 (2认同)

suv*_*007 5

简而言之,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 
Run Code Online (Sandbox Code Playgroud)