在交互模式下,Python 不保留字符串?

Posted

技术标签:

【中文标题】在交互模式下,Python 不保留字符串?【英文标题】:Python not interning strings when in interactive mode? 【发布时间】:2017-06-09 22:37:06 【问题描述】:

在 Python 交互式会话中:

In [1]: a = "my string"

In [2]: b = "my string"

In [3]: a == b
Out[3]: True

In [4]: a is b
Out[4]: False

In [5]: import sys

In [6]: print(sys.version)
3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609]

另一方面,当运行以下程序时:

#!/usr/bin/env python

import sys


def test():
    a = "my string"
    b = "my string"
    print(a == b)
    print(a is b)


if __name__ == "__main__":
    test()
    print(sys.version)

输出是:

True
True
3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609]

为什么a is b在上述两种情况下结果不同?

我知道this 的答案(当然还有==is 运算符之间的区别!这是问题的重点!)但不是@987654329 @ 和 b 在第一种情况下也是同一个对象吗? (interpeter?)因为它们指向相同的(不可变的)字符串?

【问题讨论】:

Is there a difference between `==` and `is` in Python?的可能重复 您必须检查 cpython 源代码,但我想 python 解释器足够聪明,可以意识到这两个字符串是相同的,并且由于字符串是不可变的,因此可以安全地指向两者变量到同一个实例。因此,is 检查返回 true。对于 REPL,因为字符串是增量输入的,所以没有这样的优化机会,两个变量都引用不同的对象。 @AminEtesamian 据我了解,问题在于为什么在使用解释器时 id 不同,但在运行 .py 文件时却相同。我认为 pkaramol 了解 is 和 == 之间的区别。 我相信 Paul 是正确的,在解释的时候有一个自省和重用的机会,在解释器中它只是制造了一个新的对象。 【参考方案1】:

所以控制台在创建两个字符串时会创建两个不同的对象,但是解释器在单个函数中运行代码时会重用相同字符串的内存位置。以下是检查您是否发生这种情况的方法:

a = "my string"
b = "my string"

print id(a)
print id(b)

如果这两个id相同,则a is b将返回True,否则返回False

看起来你正在使用 anaconda,所以我在控制台中检查了这个并发现了不同的 id,然后在编辑器中编写了一个函数并执行它并得到了相同的 id。

注意:既然我们知道is 确定两个变量标签是否指向内存中的同一个对象,我应该说应该谨慎使用is。例如,它通常用于比较像 None a is None 这样的单例。所以不要用它来比较对象,使用==,在创建类的时候实现__eq__方法,这样就可以使用==操作符了。

【讨论】:

【参考方案2】:

这是由string interning 引起的。另一个例子见this question。

在您的示例中,CPython 在模块中实习字符串常量,但不在 REPL 中。

【讨论】:

更多信息请参见this 回答。 更正。这不是字符串实习的过错。这与不断折叠有关。见here @GRAYgoose124 是对的,代码对象对其常量进行重复数据删除。此外,示例字符串包含一个空格,并且默认情况下不包含在内。请写一个答案,我会删除我的。

以上是关于在交互模式下,Python 不保留字符串?的主要内容,如果未能解决你的问题,请参考以下文章

print, repr, str, eval,exec使用

print, repr, str, eval,exec使用

Python在交互环境敲代码时怎么换行,每次一按Enter键就直接执行程序了,可是代码还没有写完啊

Python的用户交互模式

在交互模式下在python中执行多行语句

Python字符串处理:过滤字符串中的英文与符号,保留汉字