何时使用 StringIO,而不是连接字符串列表?

发布于 2024-10-12 21:51:22 字数 650 浏览 5 评论 0原文

使用 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

Using StringIO as string buffer is slower than using list as buffer.

When is StringIO used?

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

Results:

16.7872819901
18.7160351276

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

纵性 2024-10-19 21:51:22

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

The main advantage of StringIO is that it can be used where a file was expected. So you can do for example (for 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()
卸妝后依然美 2024-10-19 21:51:22

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

来自文档

模块cStringIO提供了一个
界面类似于
StringIO 模块。大量使用
可以制作 StringIO.StringIO 对象
使用该函数更有效
改为使用此模块中的 StringIO()。

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

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

If you measure for speed, you should use cStringIO.

From the docs:

The module cStringIO provides an
interface similar to that of the
StringIO module. Heavy use of
StringIO.StringIO objects can be made
more efficient by using the function
StringIO() from this module instead.

But the point of StringIO is to be a file-like object, for when something expects such and you don't want to use actual files.

Edit: I noticed you use from io import StringIO, so you are probably on Python >= 3 or at least 2.6. The separate StringIO and cStringIO are gone in Py3. Not sure what implementation they used to provide the io.StringIO. There is io.BytesIO too.

黯淡〆 2024-10-19 21:51:22

好吧,我不知道我是否愿意将其用作“缓冲区”,您只是以两种复杂的方式将字符串 a 乘以 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 是没有意义的,这是完全不同的东西,即具有类似文件流接口的字符串。

Well, I don't know if I would like to call that using it as a "buffer", you are just multiplying a string a 100 times, in two complicated ways. Here is an uncomplicated way:

def meth3(string):
    return string * 100

If we add that to your test:

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

It turns out to be way faster as a bonus:

21.0300650597
22.4869811535
0.811429977417

If you want to create a bunch of strings, and then join them, meth1() is the correct way. There is no point in writing it to StringIO, which is something completely different, namely a string with a file-like stream interface.

善良天后 2024-10-19 21:51:22

另一种方法基于 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())

结果(秒):

甲基1 = 7.731315963647944

甲基2 = 9.609279402186985

甲基3 = 0.26534052061106195

甲基4 = 2.915035489152274

Another approach based on Lennart Regebro approach.
This is faster than list method (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())

Results (sec.):

meth1 = 7.731315963647944

meth2 = 9.609279402186985

meth3 = 0.26534052061106195

meth4 = 2.915035489152274

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文