如何避免子字符串

6 投票
6 回答
504 浏览
提问于 2025-04-16 08:46

我现在处理字符串的某些部分是这样做的:

for (i, j) in huge_list_of_indices:
    process(huge_text_block[i:j])

我想避免生成这些临时子字符串带来的额外开销。有没有什么好主意?也许可以用某种方式利用索引偏移的包装器?这目前是我的瓶颈。

注意,process() 是另一个需要字符串作为输入的 Python 模块。

编辑:

有些人怀疑这是否真的是个问题。这里有一些示例结果:

import time
import string
text = string.letters * 1000

def timeit(fn):
    t1 = time.time()
    for i in range(len(text)):
        fn(i)
    t2 = time.time()
    print '%s took %0.3f ms' % (fn.func_name, (t2-t1) * 1000)

def test_1(i):
    return text[i:]

def test_2(i):
    return text[:]

def test_3(i):
    return text

timeit(test_1)
timeit(test_2)
timeit(test_3)

输出:

test_1 took 972.046 ms
test_2 took 47.620 ms
test_3 took 43.457 ms

6 个回答

1

如果你在使用Python3,可以利用协议缓冲区和内存视图。假设这些文本存储在你的文件系统中的某个地方:

f = open(FILENAME, 'rb')
data = bytearray(os.path.getsize(FILENAME))
f.readinto(data)

mv = memoryview(data)

for (i, j) in huge_list_of_indices:
    process(mv[i:j])

另外,你可以看看这篇文章,可能会对你有帮助。

3

是的,使用索引偏移量来包装一个内存映射对象是可行的。

不过在你这么做之前,确定一下生成这些子字符串真的是个问题吗?在你搞清楚时间和内存到底花在哪里之前,不要急着优化。我觉得这应该不是个大问题。

8

我觉得你想要的东西是 缓冲区

缓冲区的特点是,它们可以“切片”一个支持缓冲区接口的对象,而不需要复制它的内容,实际上是打开了一个“窗口”,可以看到切片对象的内容。想了解更技术性的解释,可以点击 这里。以下是一个摘录:

用C语言实现的Python对象可以导出一组叫做“缓冲区接口”的函数。这些函数可以让对象以原始的、字节为基础的格式暴露它的数据。对象的使用者可以通过缓冲区接口直接访问对象的数据,而不需要先复制一份。

在你的情况下,代码大概应该是这样的:

>>> s = 'Hugely_long_string_not_to_be_copied'
>>> ij = [(0, 3), (6, 9), (12, 18)]
>>> for i, j in ij:
...     print buffer(s, i, j-i)  # Should become process(...)
Hug
_lo
string

希望对你有帮助!

撰写回答