3

为什么都textwrap.wrap()那么textwrap.fill()慢?例如,在我的笔记本电脑上包装一个 10000 个字符的字符串需要将近两秒半的时间。

$ python -m timeit -n 10 -s 's = "A" * 10000; import textwrap' 'textwrap.fill(s)'
10 loops, best of 3: 2.41 sec per loop

将其与改编自相关 Stack Overflow 问题的答案的代码进行比较

#!/usr/bin/env python
# simplewrap.py
def fill(text, width=70):
    return '\n'.join(text[i:i+width] for i in
                     range(0, len(text), width))

它将文本包装速度比以下数量级快textwrap

$ python -m timeit -n 10 -s 's = "A" * 10000; import simplewrap' 'simplewrap.fill(s)'
10 loops, best of 3: 37.2 usec per loop
4

3 回答 3

8

对代码进行分析表明,时间被正则表达式所占用,该正则表达式旨在将输入拆分为单词。显示相同问题的精简版是:

import re
s = "A" * 10000
wordsep_re = re.compile(
    r'\w+[^\W]-'
    )
wordsep_re.split(s)

我相信 Python 使用递归回溯来匹配正则表达式。我认为发生的事情是python一直在尝试匹配 - 并且失败了,因此不得不备份。

您可以使用:

textwrap.fill(s, break_on_hyphens = False)

你会发现它真的很快。当文本中没有任何空格时,用于匹配连字符的正则表达式具有病态的情况。

于 2012-08-02T16:29:05.170 回答
6

textwrap比您简单、流线型的示例程序所做的要多得多。它构造一个新类,编译一些正则表达式来处理各种空格和其他可换行的字符组合等。

这并不是一个真正公平的比较,特别是因为(正如 hamstergene 指出的那样)您引用的程序实际上并未包装文本。

于 2012-08-02T16:02:00.630 回答
2

你正在测试一个特定的病理病例。一个单一的、不可破坏的字符串表现得非常糟糕:

~: python -m timeit -n 10 -s 's = "A"*10000; import textwrap' 'textwrap.fill(s)'
10 loops, best of 3: 1.62 sec per loop

但是 1000 个单词,每个单词有 9 个字符,用空格分隔,运行速度要快 300 倍:

~: python -m timeit -n 10 -s 's = "AAAAAAAAA " * 1000; import textwrap' 'textwrap.fill(s)'
10 loops, best of 3: 5.46 msec per loop
于 2012-08-02T17:22:49.907 回答