53

使用 StringIO 作为字符串缓冲区比使用列表作为缓冲区要慢。

什么时候使用 StringIO?

from io import StringIO


def meth1(string):
    a = []
    for i in range(100):
        a.append(string)
    return ''.join(a)

def meth2(string):
    a = StringIO()
    for i in range(100):
        a.write(string)
    return a.getvalue()


if __name__ == '__main__':
    from timeit import Timer
    string = "This is test string"
    print(Timer("meth1(string)", "from __main__ import meth1, string").timeit())
    print(Timer("meth2(string)", "from __main__ import meth2, string").timeit())

结果:

16.7872819901
18.7160351276
4

4 回答 4

35

StringIO 的主要优点是它可以在需要文件的地方使用。例如,您可以这样做(对于 Python 2):

import sys
import StringIO

out = StringIO.StringIO()
sys.stdout = out
print "hi, I'm going out"
sys.stdout = sys.__stdout__
print out.getvalue()
于 2011-01-19T09:51:57.443 回答
27

如果你测量速度,你应该使用cStringIO.

文档

模块 cStringIO 提供了一个类似于 StringIO 模块的接口。通过使用此模块中的函数 StringIO() 可以更有效地使用 StringIO.StringIO 对象。

但是 StringIO 的重点是成为一个类似文件的对象,因为当某些东西期望这样并且您不想使用实际文件时。

编辑:我注意到你使用from io import StringIO,所以你可能在 Python >= 3 或至少 2.6 上。单独的 StringIO 和 cStringIO 在 Py3 中消失了。不确定他们使用什么实现来提供 io.StringIO。也有io.BytesIO

于 2011-01-19T09:51:42.893 回答
18

好吧,我不知道我是否愿意把它称为“缓冲区”,你只是用两种复杂的方式将一个字符串乘以 100 次。这是一个简单的方法:

def meth3(string):
    return string * 100

如果我们将其添加到您的测试中:

if __name__ == '__main__':

    from timeit import Timer
    string = "This is test string"
    # Make sure it all does the same:
    assert(meth1(string) == meth3(string))
    assert(meth2(string) == meth3(string))
    print(Timer("meth1(string)", "from __main__ import meth1, string").timeit())
    print(Timer("meth2(string)", "from __main__ import meth2, string").timeit())
    print(Timer("meth3(string)", "from __main__ import meth3, string").timeit())

事实证明,作为奖励,它的速度更快:

21.0300650597
22.4869811535
0.811429977417

如果你想创建一堆字符串,然后加入它们,meth1() 是正确的方法。将它写入 StringIO 是没有意义的,这是完全不同的东西,即具有类似文件的流接口的字符串。

于 2011-01-19T10:10:14.230 回答
-1

另一种方法基于 Lennart Regebro 方法。这比列表方法(meth1)更快

def meth4(string):
    a = StringIO(string * 100)
    contents = a.getvalue()
    a.close()
    return contents

if __name__ == '__main__':
    from timeit import Timer
    string = "This is test string"
    print(Timer("meth1(string)", "from __main__ import meth1, string").timeit())
    print(Timer("meth2(string)", "from __main__ import meth2, string").timeit())
    print(Timer("meth3(string)", "from __main__ import meth3, string").timeit())
    print(Timer("meth4(string)", "from __main__ import meth4, string").timeit())

结果(秒):

meth1 = 7.731315963647944

meth2 = 9.609279402186985

meth3 = 0.26534052061106195

meth4 = 2.915035489152274

于 2018-03-14T05:57:03.670 回答