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

发布于 2021-01-29 17:21:53

我试图了解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

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

考虑到这一点,似乎很明显Example 1return True
(对我而言)Example 2返回仍然是显而易见的True

对我来说,Example 3返回并不明显False-我不是在做与Example 2?!中相同的事情吗?

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

并通读http://guilload.com/python-string-interning/(尽管我可能不太了解),然后再读-好的,也许“
interned”字符串取决于长度,所以我HelloHelloHelloHelloHello在中使用了Example 4。结果是True

而令我困惑的是,这样做Example 2与使用更大的数字相同(但实际上会返回与相同的字符串Example 4),但是这次的结果是False?!

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

是否有任何官方资料可以解释这种现象?

关注者
0
被浏览
280
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    您发布的链接

    避免大型.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;
    }
    

    编辑2:

    实际上
    ,该优化代码最近已移至适用于Python
    3.7的AST优化器中,因此,您现在必须调查一下ast_opt.cfunction函数fold_binop,该函数现在调用now函数safe_multiply,该函数检查字符串是否不超过MAX_STR_SIZE新定义为4096。因此,似乎对于下一个版本的限制已大大提高。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看