如何让Python共用相同字符串的内存空间?

10

可能是重复问题:
Python中的intern是做什么的,何时应该使用它?

我正在使用Python编写一个程序,需要对包含数百万个字符串对象的数组进行相关操作。我发现,如果它们都来自同一带引号的字符串,每个附加的"字符串"只是对第一个主字符串的引用。但是如果这些字符串从文件中读取,并且这些字符串都相等,则每个字符串仍然需要新的内存分配。

也就是说,这大约需要14兆字节的存储空间:

a = ["foo" for a in range(0,1000000)]

虽然这需要超过65兆的存储空间:

a = ["foo".replace("o","1") for a in range(0,1000000)]

现在我可以使用以下代码使内存占用更小:

s = {"f11":"f11"}
a = [s["foo".replace("o","1")] for a in range(0,1000000)]

但这似乎有些愚蠢。有没有更简单的方法来做到这一点?


5
@Maulwurfn,答案相同并不意味着问题相同。 - Mark Ransom
为什么不先存储replace操作的值呢? - JBernardo
1
你是如何测量列表的大小的?如果我使用 sys.getsizeof(["foo" for a in range(0,1000000)]),我得到的大小与 sys.getsizeof(["foo".replace("o","1") for a in range(0,1000000)]) 相同 -- 至少在 Python 3.2 中。 - the wolf
@JBernardo,我没有先存储“replace”操作的值,因为我有意尝试生成字符串,而不是对旧字符串的大量引用。 - vy32
3个回答

14

只需要执行一个 intern(),它会让 Python 将字符串存储在内存中并从中获取:

a = [intern("foo".replace("o","1")) for a in range(0,1000000)]

这也会得到大约18MB的结果,与第一个示例相同。

还请注意下面的评论,如果您使用的是Python3,请谢谢@Abe Karplus。


2
请注意,Python 3 中 intern 已被重命名为 sys.intern - Abe Karplus
1
+1 我不知道 intern() - Ashwini Chaudhary
1
谢谢,太好了。谢谢。我不知道intern的用法。是的,我正在使用Python3,所以我需要使用sys.intern()。 - vy32

0
您可以尝试像这样做:

strs=["this is string1","this is string2","this is string1","this is string2",
      "this is string3","this is string4","this is string5","this is string1",
      "this is string5"]
new_strs=[]
for x in strs:
    if x in new_strs:
        new_strs.append(new_strs[new_strs.index(x)]) #find the index of the string
                                                     #and instead of appending the
                                                #string itself, append it's reference.
    else:
        new_strs.append(x)

print [id(y) for y in new_strs]

相同的字符串现在将具有相同的id()

输出:

[18632400, 18632160, 18632400, 18632160, 18651400, 18651440, 18651360, 18632400, 18651360]

好主意。不幸的是,这是一个O(n**2)算法,随着列表变得越来越长,它会变得非常慢。 - Mark Ransom

-1
保持一个已经出现过的字符串字典应该可以解决问题。
new_strs = []
str_record = {}
for x in strs:
    if x not in str_record:
        str_record[x] = x
    new_strs.append(str_record[x])

(Untested.)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接