我来自c background和python中的初学者。我想知道在python的情况下字符串实际上是如何存储在内存中的。
我做了类似
的事情s="foo"
id(s)=140542718184424
id(s[0])= 140542719027040
id(s[1])= 140542718832152
id(s[2])= 140542718832152
我不明白每个字符是如何存储在内存中的,以及为什么s的id不等于s [0]的id(就像它在c中一样)以及为什么s1和s2的id相同?
答案 0 :(得分:4)
Python没有字符。索引到一个字符串会创建一个新的字符串,如果你不保持对它的引用,它会像其他所有对象一样迅速征服。因此,示例中的id()
无法相互比较,只要对象存在,对象的id才是唯一的。特别是id(s[0]) != id(s)
,因为前者是一个新的(临时)对象,id(s[1]) == id(s[2])
因为在第一个操作数被评估之后,第一个临时字符串被销毁,第二个临时字符串被分配给之前释放的记忆。后者是一个实现细节和巧合,不能依赖。
关于字符串内存的推理由于实现细节(例如小字符串(以及整数,一些元组等)被实现而变得更加复杂,因此some_str is other_str
对于来自不同来源的相等字符串可能是真的(例如来自索引到具有不同索引的字符串中。)
答案 1 :(得分:0)
这是依赖于实现的,但是一些实现(不仅是Python,其他语言)也可以为预期的频繁使用保留一组中等大小的常量值。在Python的情况下,那些可能是True
,None
,'o'
,1
,2
等值。这样,当其中一个常见值是需要,创建它没有任何开销 - 只需参考现有值。
答案 2 :(得分:0)
这 article 是一本很好的读物,它解释了字符串的存储方式。简而言之:
<块引用>当处理空字符串或一个字符的 ASCII 字符串时,Python 使用字符串实习。 Interned 字符串充当单例,也就是说,如果您有两个相同的字符串被 interned,则它们在内存中只有一个副本。
Python 在内部没有使用 UTF-8 来提供对子字符串的持续访问:
s = 'hello world'
s[0]
s[7]
两者都不需要将字符串从初始字符(或更准确地说,长度为 1 的第一个子字符串)扫描到 i-th
位置。
这就是为什么 Python 对 Unicode 字符串使用三种内部表示,每个字符有 1、2 或 4 个字节(Latin-1、UCS-2、UCS-4 编码)并且不使用空格-优化的 UTF-8。