何时使用StringIO,而不是加入字符串列表?

时间:2011-01-19 09:39:21

标签: python stringio

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

何时使用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 个答案:

答案 0 :(得分:32)

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()

答案 1 :(得分:26)

如果您测量速度,则应使用cStringIO

来自docs

  

模块cStringIO提供了一个   界面类似于   StringIO模块。大量使用   可以创建StringIO.StringIO对象   使用该功能更有效   而是来自这个模块的StringIO()。

但是StringIO的目的是成为一个类似的文件对象,因为当某些事情需要时,你不想使用实际的文件。

编辑:我注意到您使用from io import StringIO,因此您可能使用的是Python> = 3或至少2.6。单独的StringIO和cStringIO在Py3中消失了。不确定他们用于提供io.StringIO的实现。还有io.BytesIO

答案 2 :(得分:17)

好吧,我不知道我是否愿意将它称为“缓冲区”,你只是将字符串乘以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是没有意义的,这是完全不同的东西,即具有类似文件的流接口的字符串。

答案 3 :(得分:-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