gpt4 book ai didi

Python 的不可变字符串及其切片

转载 作者:太空狗 更新时间:2023-10-29 21:43:33 25 4
gpt4 key购买 nike

Python 中的字符串是不可变的,并且支持缓冲区接口(interface)。在使用切片或 .split() 方法时,不返回新字符串,而是返回指向旧字符串部分的缓冲区可能是有效的。但是,每次都会构造一个新的字符串对象。为什么?我看到的唯一原因是它会使垃圾收集变得更加困难。

正确:在常规情况下,内存开销是线性的并且不明显。复制很快,分配也很快。但是 Python 已经做的太多了,所以也许这样的缓冲区值得付出努力?

编辑:

似乎以这种方式形成子字符串会使内存管理变得更加复杂。只使用了任意字符串的 20%,并且我们无法释放字符串的其余部分的情况是一个简单的示例。我们可以改进内存分配器,这样它就可以部分地解除分配字符串,但这可能主要是一个反证。如果内存变得关键,所有标准函数都可以用 buffermemoryview 模拟。代码不会那么简洁,但必须放弃一些东西才能得到一些东西。

最佳答案

底层字符串表示是null-terminated,即使它会跟踪长度,因此您不能有一个引用子字符串的字符串对象是不是后缀。这已经限制了您的提案的实用性,因为它会增加很多复杂性来以不同方式处理足够和非足够(并且放弃空终止字符串会带来其他后果)。

允许引用字符串的子字符串意味着很多垃圾收集和字符串处理复杂化。对于每个字符串,您必须跟踪有多少对象引用每个字符或每个索引范围。这意味着使字符串对象的 struct 以及处理它们的任何操作变得复杂,这意味着可能会大大降低速度。

添加一个事实,从 python3 开始,字符串有 3 种不同的内部表示,而且事情会变得太乱而无法维护,并且您的提议可能没有提供足够的好处而无法被接受。


这种“优化”的另一个问题是当你想释放“大字符串”时:

a = "Some string" * 10 ** 7
b = a[10000]
del a

在这个操作之后,你有子字符串 b 来阻止 a ,一个巨大的字符串,被释放。当然,您可以复制小字符串,但是如果 b = a[:10000](或另一个大数字)怎么办? 10000 个字符看起来像一个大字符串,应该使用优化来避免复制,但它阻止释放兆字节的数据。垃圾收集器必须不断检查是否值得释放一个大字符串对象并制作副本,并且所有这些操作必须尽可能快,否则最终会降低时间性能。

程序中使用的字符串在 99% 的情况下都是“小”的(最多 10k 个字符),因此复制非常快,而您建议的优化开始对非常大的字符串有效(例如,采用大小为 100k 的子字符串来自巨大的文本)并且对于非常小的字符串要慢得多,这是常见的情况,即应该优化的情况。


如果您认为重要,那么您可以自由地提出一个 PEP,展示一个实现以及您的提案在速度/内存使用方面的结果变化。如果它真的值得付出努力,它可能会包含在未来版本的 python 中。

关于Python 的不可变字符串及其切片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18042042/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com