Python如何确定两个字符串是否相同

Mik*_*tty 13 python memory string

我试图理解Python字符串何时相同(也就是共享相同的内存位置).但是在我的测试中,当两个相等的字符串变量共享相同的内存时似乎没有明显的解释:

import sys
print(sys.version) # 3.4.3

# Example 1
s1 = "Hello"
s2 = "Hello"
print(id(s1) == id(s2)) # True

# Example 2
s1 = "Hello" * 3
s2 = "Hello" * 3
print(id(s1) == id(s2)) # True

# Example 3
i = 3
s1 = "Hello" * i
s2 = "Hello" * i
print(id(s1) == id(s2)) # False

# Example 4
s1 = "HelloHelloHelloHelloHello"
s2 = "HelloHelloHelloHelloHello"
print(id(s1) == id(s2)) # True

# Example 5
s1 = "Hello" * 5
s2 = "Hello" * 5
print(id(s1) == id(s2)) # False
Run Code Online (Sandbox Code Playgroud)

字符串是不可变的,据我所知,Python尝试重用现有的不可变对象,让其他变量指向它们,而不是在内存中使用相同的值创建新对象.

考虑到这一点,Example 1回报似乎显而易见True.
(对我而言)Example 2回归仍然是显而易见的True.

这对我来说并不明显,那Example 3回归False- 我不是在做同样的事情Example 2吗?!?

我偶然发现了这个问题:
为什么使用'=='或'is'来比较Python中的字符串有时会产生不同的结果?

并通过阅读http://guilload.com/python-string-interning/(虽然我可能不明白这一切)和thougt -好吧,也许"实习"的字符串取决于长度,所以我用HelloHelloHelloHelloHelloExample 4.结果是True.

令我感到困惑的是,Example 2只是用更大的数字做同样的事情(但它会有效地返回相同的字符串Example 4) - 但是这次结果是False什么?!?

我真的不知道Python如何决定是否使用相同的内存对象,或何时创建一个新的内存对象.

是否可以解释这种行为的官方来源?

jde*_*esa 10

您发布的链接:

避免使用大型.pyc文件

那么为什么不'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa'评价True呢?你还记得你在所有软件包中遇到的.pyc文件吗?好吧,Python字节码存储在这些文件中.如果有人写了这样的话['foo!'] * 10**9会怎么样?生成的.pyc文件将是巨大的!为了避免这种现象,如果它们的长度优于20,则通过窥视孔优化产生的序列被丢弃.

如果你有字符串"HelloHelloHelloHelloHello",Python必须按原样存储它(要求解释器检测字符串中的重复模式以节省空间可能太多).但是,当涉及到可以在解析时计算的字符串值时,例如"Hello" * 5,Python将这些值作为所谓的"窥孔优化"的一部分进行评估,这可以决定是否值得预先计算字符串.因为len("Hello" * 5) > 20,解释器保留它以避免存储太多长串.

编辑:

本问题所示,您可以在源代码中查看peephole.c,函数fold_binops_on_constants,接近结尾,您将看到:

// ...
} else if (size > 20) {
    Py_DECREF(newconst);
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

编辑2:

实际上,这个优化代码最近已经转移到了AST优化器,所以现在你必须查看ast_opt.c函数fold_binop,现在调用函数safe_multiply,它检查字符串是否不再MAX_STR_SIZE,新定义为4096.因此,下一版本的限制似乎已大大提升.