理解“is”运算符[重复]

2024-11-29 08:41:00
admin
原创
166
摘要:问题描述:该is运算符并不匹配变量的值,而是匹配实例本身。这究竟意味着什么?我声明了两个名为的变量x,并y在两个变量中分配相同的值,但是当我使用is运算符时,它返回 false。我需要澄清一下。这是我的代码:x = [1, 2, 3] y = [1, 2, 3] print(x is y) # False...

问题描述:

is运算符并不匹配变量的值,而是匹配实例本身。

这究竟意味着什么?

我声明了两个名为的变量x,并y在两个变量中分配相同的值,但是当我使用is运算符时,它返回 false。

我需要澄清一下。这是我的代码:

x = [1, 2, 3]
y = [1, 2, 3]

print(x is y)  # False

解决方案 1:

您误解了运算符测试的内容is。它测试两个变量是否指向同一个对象,而不是两个变量是否具有相同的值。

is来自操作员的文档:

运算符isis not测试对象身份:x is y当且仅当xy是同一个对象时才为真。

请使用==运算符:

print(x == y)

这将打印True.xy两个单独的列表:

x[0] = 4
print(y)  # prints [1, 2, 3]
print(x == y)   # prints False

如果您使用该id()函数,您将看到xy具有不同的标识符:

>>> id(x)
4401064560
>>> id(y)
4401098192

但是如果你要分配yx那么两者都指向同一个对象:

>>> x = y
>>> id(x)
4401064560
>>> id(y)
4401064560
>>> x is y
True

is表明两者是同一个对象,它返回True

请记住,在 Python 中,名称只是引用值的标签;您可以让多个名称指向同一个对象。is告诉您两个名称是否指向同一个对象。==告诉您两个名称是否引用具有相同值的对象。

解决方案 2:

另一个重复的问题询问为什么两个相等的字符串通常不相同,但这里并没有真正回答这个问题:

>>> x = 'a' 
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False

那么,为什么它们不是同一个字符串?特别是考虑到这一点:

>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True

我们先把第二部分推迟一下。第一部分怎么可能是真的呢?

解释器必须有一个“驻留表”,即一个将字符串值映射到字符串对象的表,因此每次您尝试使用内容创建新字符串时'abc',都会返回相同的对象。维基百科对驻留的工作原理有更详细的讨论。

并且 Python一个字符串驻留表;您可以使用该方法手动驻留字符串sys.intern

事实上,Python允许自动驻留任何不可变类型,但这不是必须的。不同的实现将驻留不同的值。

CPython(如果您不知道您正在使用的实现,则指您正在使用的实现)自动驻留小整数和一些特殊的单例,如False,但不驻留字符串(或大整数、小元组或其他任何东西)。您可以很容易地看到这一点:

>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False

好的,但是为什么zw相同呢?

这不是解释器自动驻留,而是编译器折叠值。

如果相同的编译时字符串在同一个模块中出现两次(这到底意味着什么很难定义——它与字符串文字不同,因为r'abc''abc''a' 'b' 'c'都是不同的文字但是是相同的字符串——但直观上很容易理解),编译器只会创建该字符串的一个实例,并带有两个引用。

事实上,编译器可以更进一步:'ab' + 'c'可以被优化器转换为'abc',在这种情况下它可以与'abc'同一个模块中的常量一起折叠。

再次强调,这是 Python 允许但不需要做的事情。但在这种情况下,CPython 总是折叠小字符串(以及例如小元组)。(尽管交互式解释器的逐语句编译器不会运行与一次模块编译器相同的优化,因此您不会以交互方式看到完全相同的结果。)


那么,作为一名程序员,你应该怎么做呢?

嗯……没什么。你几乎从来没有理由关心两个不可变值是否相同。如果你想知道什么时候可以使用a is b而不是a == b,那你就问错了。a == b在两种情况下始终使用 except 即可:

  • 为了与单例值进行更易读的比较,例如x is None

  • 对于可变值,当您需要知道变异是否x会影响时y

解决方案 3:

is仅当它们实际上是同一个对象时才返回 true。如果它们相同,对其中一个的更改也会反映在另一个中。以下是差异的一个例子。

>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> print x is y
False
>>> z = y
>>> print y is z
True
>>> print x is z
False
>>> y[0] = 5
>>> print z
[5, 2, 3]

解决方案 4:

受重复问题的提示,这个类比可能有效:

# - Darling, I want some pudding!
# - There is some in the fridge.

pudding_to_eat = fridge_pudding
pudding_to_eat is fridge_pudding
# => True

# - Honey, what's with all the dirty dishes?
# - I wanted to eat pudding so I made some. Sorry about the mess, Darling.
# - But there was already some in the fridge.

pudding_to_eat = make_pudding(ingredients)
pudding_to_eat is fridge_pudding
# => False

解决方案 5:

isis not是 Python 中的两个恒等运算符。is运算符不比较变量的值,而是比较变量的恒等。考虑一下:

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> hex(id(a))
'0x1079b1440'
>>> hex(id(b))
'0x107960878'
>>> a is b
False
>>> a == b
True
>>>

上面的例子表明,和的标识(在 Cpython 中也可以是内存地址)是不同的ab即使它们的值相同)。这就是为什么当您说时,a is b它会返回 false,因为两个操作数的标识不匹配。但是当您说时a == b,它会返回 true,因为该==操作仅验证两个操作数是否都分配了相同的值。

有趣的例子(针对额外等级):

>>> del a
>>> del b
>>> a = 132
>>> b = 132
>>> hex(id(a))
'0x7faa2b609738'
>>> hex(id(b))
'0x7faa2b609738'
>>> a is b
True
>>> a == b
True
>>>

在上面的例子中,尽管ab是两个不同的变量,但a is b返回的是True。这是因为的类型a是,int它是一个不可变对象。所以python(我猜是为了节省内存)b在创建时将相同的对象分配给了相同的值。所以在这种情况下,变量的身份匹配,a is b结果是True

这将适用于所有不可变对象:

>>> del a
>>> del b
>>> a = "asd"
>>> b = "asd"
>>> hex(id(a))
'0x1079b05a8'
>>> hex(id(b))
'0x1079b05a8'
>>> a is b
True
>>> a == b
True
>>>

希望有所帮助。

解决方案 6:

x is y与 相同id(x) == id(y),比较对象的身份。

正如@tomasz-kurgan 在下面的评论中指出的那样,is运算符对某些对象的行为异常。

例如

>>> class A(object):
...   def foo(self):
...     pass
... 
>>> a = A()
>>> a.foo is a.foo
False
>>> id(a.foo) == id(a.foo)
True

参考:

https://docs.python.org/2/reference/expressions.html#is-not

https://docs.python.org/2/reference/expressions.html#id24

解决方案 7:

正如您在此处看到的,这是一个小整数。 257 以上的数字不是小整数,因此它被计算为不同的对象。

==在这种情况下最好使用。

更多信息请参见:http: //docs.python.org/2/c-api/int.html

解决方案 8:

X 指向一个数组,Y 指向另一个数组。这两个数组是相同的,但is运算符将查看不相同的指针。

解决方案 9:

它比较对象身份,即变量是否引用内存中的同一个对象。它类似于==Java 或 C 中的(比较指针时)。

解决方案 10:

一个水果的简单例子

fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist is newfruitlist )
print ( fruitlist is verynewfruitlist )
print ( newfruitlist is verynewfruitlist )

输出:

True
False
False

如果你尝试

fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist == newfruitlist )
print ( fruitlist == verynewfruitlist )
print ( newfruitlist == verynewfruitlist )

输出不同:

True
True
True

这是因为 == 运算符仅比较变量的内容。要比较两个变量的身份,请使用is运算符

打印识别号码:

print ( id( variable ) )

解决方案 11:

is运算符只不过是 的英文版本==。由于两个列表的 ID 不同,因此答案为 false。您可以尝试:

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

*因为两个列表的 ID 相同

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用