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

18 浏览
0 Comments

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

我的 Google-fu 失效了。

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

n = 5

# 测试一

if n == 5:

print 'Yay!'

# 测试二

if n is 5:

print 'Yay!'

这对于比较实例(比如一个列表)的对象是否成立?

好吧,这差不多回答了我的问题:

L = []

L.append(1)

if L == [1]:

print 'Yay!'

# 成立,但是...

if L is [1]:

print 'Yay!'

# 不成立。

所以,== 测试的是值,而 is 测试的是是否为同一对象?

0
0 Comments

"=="和"is"之间有什么区别吗?

在Python中,"=="和"is"是用于比较对象的操作符。然而,它们之间有一个重要的区别。

"=="用于值的比较,即判断两个对象的值是否相等。当你想知道两个对象的值是否相等时,应该使用"=="。

"is"用于引用的比较,即判断两个引用是否指向同一个对象。当你想知道两个引用是否指向同一个对象时,应该使用"is"。

一般来说,当你比较的是简单类型时,通常是在检查值的相等性,所以应该使用"=="。例如,你的例子的意图可能是检查x是否具有与2相等的值,而不是x是否实际上引用了与2相同的对象。

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

这是我们预期的结果:a和b具有相同的值,但是它们是不同的实体。但是下面的例子呢?

这与之前的结果不一致。这是因为Python的引用实现在范围-5到256的整数对象上进行缓存,以提高性能。这里有一个示例来证明这一点:

这是另一个不使用"is"的明显原因:当你错误地使用它进行值的比较时,其行为由实现决定。

关于第一个例子a=500和b=500,我想指出的是,如果你将a和b设置为[-5, 256]之间的整数,a is b实际上会返回True。更多信息可以参考这里:stackoverflow.com/q/306313/7571052

总之,如果你想检查它们是否是同一个对象,可以使用"is"。如果你只关心基本类型,通常使用"=="就足够了。这是一个经验法则,当情况变得复杂时,可能会被违反。

0
0 Comments

在Python中,"=="和"is"是用来比较两个变量之间的差异的操作符。其中,"is"用于比较两个变量是否指向同一个内存对象,如果是则返回True,否则返回False;而"=="用于比较两个变量所引用的对象是否相等,如果相等则返回True,否则返回False。

以下是一些例子来说明这两个操作符的差异:

a = [1, 2, 3]
b = a
print(b is a)  # 输出True
print(b == a)  # 输出True
b = a[:]
print(b is a)  # 输出False
print(b == a)  # 输出True
print(1000 is 10**3)  # 输出False
print(1000 == 10**3)  # 输出True
print("a" is "a")  # 输出True
print("aa" is "a" * 2)  # 输出True
x = "a"
print("aa" is x * 2)  # 输出False
print("aa" is intern(x*2))  # 输出True

上述例子中,可以看到当使用"=="比较两个相同的对象时,返回值为True。而当使用"is"比较两个相同的对象时,返回值只有在某些特殊情况下才为True,比如对于小整数和字符串字面值。

此外,还需要注意的是,对于不同类型的对象进行比较时,即使它们的值相等,使用"=="操作符也会返回True。例如,5.0是一个浮点数,而5是一个整数,但是"5.0 == 5"的结果仍然为True。

总结起来,使用"=="操作符比较对象的值是否相等,而使用"is"操作符用于比较对象是否相同。在性能和鸭子类型方面,使用"is"操作符比使用"=="操作符更加高效,因为"is"操作符只比较内存地址,而"=="操作符则由对象自己决定是否定义为等于其他对象。

需要注意的是,在Python 3.8及更高版本中,当比较字面值时,使用"is"操作符会引发SyntaxWarning警告,建议使用"=="操作符。

更多相关信息,请参考:这个问题

0
0 Comments

在Python中,"=="和"is"有一个非常重要的区别。

"=="用于检查相等性,其语义是等价的对象(不一定是同一个对象)将测试为相等。根据文档的说法:

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

"is"用于检查身份,其语义是对象(在内存中)是对象本身。同样,根据文档的说法:

运算符"is"和"is not"用于测试对象身份:如果且仅当x和y是同一个对象时,x is y为真。使用"id()"函数确定对象身份。"x is not y"得到相反的真值。

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

a is b

与以下代码等价:

id(a) == id(b)

其中"id"是返回“在同时存在的对象之间保证唯一的整数”的内置函数(参见"help(id)"),而a和b是任意的对象。

其他用法说明:

您应该根据它们的语义使用这些比较。使用"is"检查身份,使用"=="检查相等性。

因此,通常我们使用"is"来检查身份。这在我们检查应该只存在一次的对象时通常很有用,这在文档中称为"singleton"。

"is"的用例包括:

- None

- 枚举值(使用enum模块的枚举)

- 通常是模块

- 通常是类定义产生的类对象

- 通常是函数定义产生的函数对象

- 任何在内存中应该只存在一次的其他对象(通常是所有单例对象)

- 您希望按身份获取的特定对象

"=="的常见用例包括:

- 数字,包括整数

- 字符串

- 列表

- 集合

- 字典

- 自定义可变对象

- 其他内置的不可变对象,在大多数情况下

对于"=="的一般用例是您想要的对象可能不是同一个对象,而是一个等价的对象。

PEP 8指南:

PEP 8是标准库的官方Python样式指南,也提到了"is"的两个用例:

- 永远使用"is"或"is not"来比较诸如"None"之类的单例,而不是使用相等运算符。

- 当测试一个默认值为"None"的变量或参数是否设置为其他值时,要小心写成"if x",而不是"if x is not None" - 例如,其他值可能具有在布尔上下文中为假的类型(例如容器)!

从身份推断相等性:

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

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

默认的相等比较行为("=="和"!=")基于对象的身份。因此,具有相同身份的实例之间的相等比较结果为相等,具有不同身份的实例之间的相等比较结果为不相等。采用这种默认行为的原因是希望所有对象都应该是自反的(即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 is nan

True

nan == nan # !!!!!

False

检查身份可以比检查相等性(可能需要递归检查成员)更快。但它不能替代在可能找到多个等同对象的情况下的相等性检查。

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

[nan] == [nan]

(True)

(nan,) == (nan,)

(True)

一个警示故事:

这个问题尝试使用"is"来比较整数。您不应该假设一个整数的实例与通过另一个引用获得的实例是同一个实例。这个故事解释了为什么。

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

这可能导致一些隐蔽的错误。我有一些代码,检查a是否为b,因为a和b通常是小数字。这个错误直到今天才发生,已经在生产中运行了六个月,因为a和b最终足够大,无法缓存。- gwg

在开发中它工作正常。它可能通过了一些单元测试。

并且它在生产中工作正常 - 直到代码检查一个大于256的整数,此时它在生产中失败。

这是一个可以在代码审查或可能使用样式检查器捕获的生产故障。

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

"完全不使用"is"也是一个好规则,但是用"== None"也可以工作...

- FrançoisFabre

另一个例外:官方文档似乎建议使用"is"来比较"Enum":

"Enum"之间的比较应该使用"is"。

Glenn,我认为最重要的是,虽然在某些情况下,身份的测试可以替代相等性的测试,在某些情况下这是可取的,但在大多数情况下这是不可取的,因此我们需要小心地根据情况选择正确的测试方法。此外,对于类型的身份测试,虽然在某些情况下可能是正确的,但不支持子类替代其父类的可替代性。

0