Python:为什么(“hello”是“hello”呢)的计算结果是真的?

Python:为什么(“hello”是“hello”呢)的计算结果是真的?,python,identity,string-comparison,object-comparison,Python,Identity,String Comparison,Object Comparison,为什么在Python中,“hello”是“hello”产生的True 我读到以下内容: 如果两个字符串文本相等,则将它们置于相同的位置 内存位置。字符串是不可变的实体。不会有伤害 完成 所以每个Python字符串在内存中只有一个位置?听起来很奇怪。这里发生了什么事?为什么奇怪。如果字符串是不可变的,那么只存储一次就很有意义。NET具有相同的行为 < Python(如java、C++、C++、.NET)使用字符串池/交互。解释器意识到“hello”与“hello”相同,因此它优化并使用内存中相同的

为什么在Python中,“hello”是“hello”产生的
True

我读到以下内容:

如果两个字符串文本相等,则将它们置于相同的位置 内存位置。字符串是不可变的实体。不会有伤害 完成


所以每个Python字符串在内存中只有一个位置?听起来很奇怪。这里发生了什么事?

为什么奇怪。如果字符串是不可变的,那么只存储一次就很有意义。NET具有相同的行为

< Python(如java、C++、C++、.NET)使用字符串池/交互。解释器意识到“hello”与“hello”相同,因此它优化并使用内存中相同的位置


另一个好处是:
“hell”+“o”是“hello”
==>
True
Python解释器/编译器解析字符串文本,即引用的字符列表。当它这样做时,它可以检测“我以前见过这个字符串”,并使用与上次相同的表示。它可以做到这一点,因为它知道以这种方式定义的字符串是不能更改的。

文字字符串可能是根据其哈希或类似内容进行分组的。两个相同的文本字符串将存储在同一内存中,任何引用都引用该字符串

 Memory        Code
-------
|          myLine = "hello"
|        /
|hello  <
|        \
|          myLine = "hello"
-------
内存代码
-------
|myLine=“你好”
|        /
|你好<
|        \
|myLine=“你好”
-------

如果两个参数是同一个对象,
is
运算符返回true。你的结果就是这个的结果,引用的位

在字符串文本的情况下,这些文本是插入的,这意味着它们将与已知字符串进行比较。如果已知相同的字符串,则文字将采用该值,而不是另一个值。因此,它们成为同一个对象,表达式为真

所以每个Python字符串在内存中只有一个位置

不,只有解释器决定优化的,这是一个基于策略的决定,该策略不属于语言规范的一部分,并且在不同的CPython版本中可能会发生变化

例如,在我的安装(2.6.2 Linux)上:

类似于ints:

>>> 2**8 is 2**8
True
>>> 2**9 is 2**9
False

因此,不要依赖“string”就是“string”:即使只看C实现也不安全。

我认为如果任何两个变量(不仅仅是字符串)包含相同的值,那么该值将只存储一次而不是两次,并且两个变量都将指向相同的位置。这节省了内存。

字符串的内部处理与不变性有什么关系?Python和“.NET”中的许多内容都是不可更改的,而不需要进行内部存储。因为如果字符串文字可以在内存中更改,则无法共享(或“内部存储”)。是的,但鉴于对象是不可变的,因此可以安全地共享对实例的引用。还可以查看用于检查内存位置的
id
函数:
print id(“hello”)
bzlm,pyref.infogami.com/intern链接已经失效,但archive.org在这里有一个副本:

然而,尽管这通常是真的,这并不总是正确的,正如@bobince在下面很好地演示的那样;“foo”==“foo”在C中通常是正确的。在C和Python中,这是一个实现细节;我认为Python中的任何东西都不需要解释器执行此操作,而在C/C++中,这是一种并非所有编译器都执行的优化,可以禁用它。(相比之下,这个属性在Lua中总是正确的;所有的字符串都是插入的。)@Glenn,你说得对,我很高兴有人提到。当然,没有人应该相信这是真的。它是c/c++等语言的解释器或编译器,具体工作是通过使编译时确定的字符串相同来进行优化。在这种特定情况下,对象是相同的,因为同一表达式中的两个文本匹配,并导致代码中存储一个常量。如果您使用
a='hell'+'o!'
b='hello!'
在交互shell中的单独行中,
a是b
将为false
a='hell'+'o'和
b='hello'`会触发实习,所以这是真的。但是把这两个例子放到一个函数中,你会得到同样的对象。对象重用有多种途径,它们总是优化的结果。不要依赖这些实现细节。因此,您应该始终使用
=
进行字符串相等性比较。解释器在Python中缓存小整数(最多256个)。因此,
a=50;b=50;a为b
为真,
a=500;b=500;“a是b
是假的。@DarshanChaudhary:后一个表达式实际上是真的,因为你把所有的作业都放在一行
500
是作为常量存储在code对象中的文字,并且
a
b
都被分配了一个常量。。。同样,实现细节,不要指望它。这正是公认的答案所说的……正如博宾斯指出的,这并不一定总是正确的。它们“成为同一个对象”?如果修改其中一个,则不会修改另一个。@endolith:所讨论的对象是插入的字符串,而不是指定给该字符串的变量。在python中,无法修改字符串。这不是真的!它只考虑字符串和小整数。例如,当您复制列表或字典时,尽管它们具有相同的值(=相等),但它们不是相同的对象(“是”相等)。这就是为什么可以在原始列表保持不变的情况下更改列表的副本(反之亦然)。O'reilly学习Python的动态类型一章中提供了很好的解释
>>> 2**8 is 2**8
True
>>> 2**9 is 2**9
False