Python:为啥 ("hello" is "hello") 评估为 True? [复制]
Posted
技术标签:
【中文标题】Python:为啥 ("hello" is "hello") 评估为 True? [复制]【英文标题】:Python: Why does ("hello" is "hello") evaluate as True? [duplicate]Python:为什么 ("hello" is "hello") 评估为 True? [复制] 【发布时间】:2010-11-26 10:03:36 【问题描述】:为什么"hello" is "hello"
在 Python 中会产生 True
?
我阅读了以下here:
如果两个字符串字面量相等,则它们被置为相同 内存位置。字符串是不可变的实体。没有伤害可以 完成。
所以每个 Python 字符串在内存中只有一个位置?听起来很奇怪。这是怎么回事?
【问题讨论】:
还可以查看用于检查内存位置的id
函数:print id("hello")
bzlm,pyref.infogami.com/intern 链接已经失效,但是 archive.org 在这里有一个副本:web.archive.org/web/20090429040354/http://pyref.infogami.com/… 然而,虽然它经常是真的,这并不总是正确的,正如@bobince 在下面很好地展示的那样。
【参考方案1】:
Python(如 Java、C、C++、.NET)使用字符串池/实习。解释器意识到“hello”和“hello”是一样的,所以它优化并使用了内存中的相同位置。
另一个好东西:"hell" + "o" is "hello"
==> True
【讨论】:
即使是 C/C++ 通常也会这样做; "foo" == "foo" 在 C 中通常是正确的。在 C 和 Python 中,这是一个实现细节;我认为 Python require 中的任何内容都不需要解释器执行此操作,而在 C/C++ 中,这是一种优化,并非所有编译器都执行此操作,并且可以禁用它。 (相比之下,这个属性在 Lua 中总是为真;所有字符串都被保留。) @Glenn,你是对的,我很高兴有人提到。当然,没有人应该相信这是真的。 它是一个解释器或编译器,用于诸如 c/C++ 等语言的特定工作,通过使编译时间确定的字符串相同来执行此优化。 在这种特定情况下,对象是相同的,因为同一表达式中的两个字面量匹配并导致存储在代码中的单个常量。如果你在交互式 shell 的不同行上使用了a = 'hell' + 'o!'
和 b = 'hello!'
,a is b
将是错误的。 a = 'hell' + 'o' and
b = 'hello'` 确实会触发实习,所以这是真的。但是将这两个示例放入一个函数中,您将再次拥有相同的对象。 对象重用有多种途径,它们总是优化的结果。不要依赖这样的实现细节。【参考方案2】:
所以每个 Python 字符串在内存中只有一个位置?
不,只有解释器决定优化的那些,这是基于不属于语言规范的政策的决定,并且可能会在不同的 CPython 版本中发生变化。
例如。在我的安装(2.6.2 Linux)上:
>>> 'X'*10 is 'X'*10
True
>>> 'X'*30 is 'X'*30
False
对于整数也类似:
>>> 2**8 is 2**8
True
>>> 2**9 is 2**9
False
所以不要依赖 'string' 就是 'string':即使只看 C 实现也不安全。
【讨论】:
因此,您应该始终使用==
进行字符串相等比较。
解释器在 Python 中缓存小整数(最多 256 个)。所以,a = 50; b = 50; a is b
是 True,a = 500; b = 500; a is b
是 False。
@DarshanChaudhary:后一个表达式实际上是 True,因为您将所有作业放在一行中。 500
是作为常量存储在代码对象中的文字,a
和 b
都被分配了一个常量……再说一次,实现细节,不要指望它。【参考方案3】:
我认为如果任何两个变量(不仅仅是字符串)包含相同的值,则该值将只存储一次而不是两次,并且两个变量都将指向同一个位置。这样可以节省内存。
【讨论】:
不是真的!它只考虑字符串和小整数。例如,当您复制列表或字典时,尽管它们具有相同的值(== 相等),但它们不是同一个对象(“is”相等)。这就是为什么您可以更改列表的副本,因为原始列表保持不变(反之亦然)。 O'reilly 在学习 Python 的 Dynamic Typing 一章中提供了很好的解释【参考方案4】:如果两个参数是同一个对象,is
运算符将返回 true。你的结果是这个和引用位的结果。
在字符串文字的情况下,这些是实习的,这意味着它们与已知字符串进行比较。如果已知相同的字符串,则文字采用该值,而不是替代值。因此,它们成为同一个对象,表达式为真。
【讨论】:
他们“成为同一个对象”?如果您修改一个,则另一个不会被修改。 @endolith:有问题的对象是被实习的字符串,而不是分配给该字符串的变量。在 python 中,没有办法修改字符串。【参考方案5】:文字字符串可能根据它们的散列或类似的东西进行分组。两个相同的文字字符串将存储在同一个内存中,任何引用都引用它。
Memory Code
-------
| myLine = "hello"
| /
|hello <
| \
| myLine = "hello"
-------
【讨论】:
这正是公认的答案所说的...... 正如 bobince 所指出的,这不一定总是正确的。【参考方案6】:Python 解释器/编译器解析字符串文字,即带引号的字符列表。当它这样做时,它可以检测到“我以前见过这个字符串”,并使用与上次相同的表示。它可以这样做,因为它知道以这种方式定义的字符串不能更改。
【讨论】:
【参考方案7】:为什么奇怪。如果字符串是不可变的,那么只存储一次就很有意义。 .NET 具有相同的行为。
【讨论】:
字符串实习与不变性有何关系? Python 和“.NET”中的许多东西都是不可变的,无需被实习。 因为如果字符串文字可以在内存中更改,它就不能被共享(或“实习”)。 是的,但鉴于对象是不可变的,因此可以安全地共享对实例的引用。以上是关于Python:为啥 ("hello" is "hello") 评估为 True? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥我在prthon写print(“hello world"),会出现无法初始化设备 PRN
Python中不定长参数这样用对吗?def hh(w,**l,pu='d'): 为啥?
Fatal error in launcher: Unable to create process using '"d:downloadpython.exe" &qu(示