Python 字符串是不可变的,那么为什么 s.split() 返回一个新字符串列表

标签 python string split python-internals

通过查看 CPython 实现,字符串 split() 的返回值似乎是新分配的字符串列表。但是,由于字符串是不可变的,因此似乎可以通过指向偏移量从原始字符串中生成子字符串。

我是否正确理解了 CPython 的当前行为?是否有理由不选择这种空间优化?我能想到的一个原因是父字符串只有在其所有子字符串都被释放后才能被释放。

最佳答案

如果没有 Crystal 球,我无法告诉您为什么 CPython 会那样做。但是,出于某些原因您可能会选择这样做。

问题是一个小字符串可能包含对更大后备数组的引用。例如,假设我读入一个 8 GB 的 HTTP 访问日志文件以分析哪些用户代理访问我的文件的次数最多,我只通过 fp.read() 执行此操作,然后在一次处理整个文件,而不是一次处理一行。

我想知道前 10 个最常见的用户代理,所以我把它放在一个列表中。

然后我想对其他 100 个文件进行相同的分析,以查看前 10 个用户代理随时间发生的变化。繁荣!我的程序试图使用 800 GB 内存并被终止。为什么?我该如何调试?

Java 在 Java 7 之前使用了这种共享技术,所以同样的推理也适用。参见 Java 7 String - substring complexityJDK-4513622: (str) keeping a substring of a field prevents GC for object .

另请注意,让字符串共享内存需要您遵循从字符串对象到字符串数据的指针。在 CPython 中,字符串数据通常直接放在内存中的 header 之后,因此您不需要跟随指针。这减少了所需的分配次数,并减少了读取字符串时的数据依赖性。

关于Python 字符串是不可变的,那么为什么 s.split() 返回一个新字符串列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43841023/

相关文章:

iOS 与 Swift 的 String .isEmpty 的兼容性

postgresql - 如何在 psql 中将一列拆分为更多列?

javascript - 如何拆分字符串对象然后连接并添加到数组

sql - 如何将地址文本列拆分为多列

python - 遍历列表 - 分割字符串

python - sh : Rscript: command not found

python - IMAP 在发件人字段中搜索电子邮件地址

C# - "\0"等同于什么?

javascript - 如何在 JavaScript 中多个子字符串中的一个第一次出现时拆分字符串?

python - 如何根据两列的条件更改结果列?