3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Pythonでの文字列連結スピード比較(2025年版)

3
Last updated at Posted at 2025-04-29

概要

Pythonで複数の文字列を連結する方法として、次の3つの方法の処理速度を比較します。

1 配列に格納して「.join()」で連結

l = []
l.append("a")
l.append("b")
l.append("c")
t = "".join(l)

print(t)
# abc

2 「StringIO」でwrite()を使う

from io import StringIO
b = StringIO()
b.write("a")
b.write("b")
b.write("c")
t = b.getvalue()

print(t)
# abc

3 文字列変数を「+」で連結

t = ""
t += "a"
t += "b"
t += "c"

print(t)
# abc

背景

大量の文字列を扱う際など、配列とjoin()を使うことが多かったのですが、サンプルコードなどではStringIOを使用しているものも見かけるため、調べてみました。

参考事例

2012年と古い記事ですが比較をしている記事がありました。

Lists vs. StringIO vs. Regular String Concat for building strings in Python

結果部分を引用します。
連結速度は
「+」<「.join()」<「StringIO」
となっています。
(注意:2025年では結果が違います)

IPython 0.10.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object'. ?object also works, ?? prints more.

In [2]: from string_building_perf import *

In [3]: %timeit build_ul_list(100000)
10 loops, best of 3: 77.9 ms per loop

In [4]: %timeit build_ul_stringio(100000)
10 loops, best of 3: 109 ms per loop

In [5]: %timeit build_ul_concat(100000)
10 loops, best of 3: 66.1 ms per loop

In [6]: %timeit build_ul_list(100000, get_random_word)
1 loops, best of 3: 245 ms per loop

In [7]: %timeit build_ul_stringio(100000, get_random_word)
1 loops, best of 3: 269 ms per loop

In [8]: %timeit build_ul_concat(100000, get_random_word)
1 loops, best of 3: 203 ms per loop

比較(2025)

同じ方法で改めて計測してみます(Python3.12.3, ipython9.2.0)。
コードの一部をPython3に合わせて修正して使わせてもらっています。

# パターン1

%timeit build_ul_list(100000)
6.34 ms ± 95.4 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit build_ul_stringio(100000)
5.76 ms ± 86.4 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit build_ul_concat(100000)
6.25 ms ± 109 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

# パターン2

%timeit build_ul_list(100000, get_random_word)
19.6 ms ± 195 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit build_ul_stringio(100000, get_random_word)
18.7 ms ± 197 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit build_ul_concat(100000, get_random_word)
18.6 ms ± 130 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

「.join()」が若干遅いくらいで他は差が少ない結果です。
パターン1では「stringIO」が少し早いです。

結果

2025年現在では、どの連結方法を使っても速度面での差は少ないと言えそうです。

利用コード

2025年の比較では次のコードを使用しています。
オリジナルはリンクを参照してください。

from io import StringIO
from itertools import permutations
import string
import random

word = 'x' * 8
words = [''.join(p) for p in permutations(string.ascii_letters [:8])]

def get_8x():
    return word

def get_random_word():
    return random.choice(words)

def build_ul_list(linect, get_word=get_8x):
    buffer = ['<ul>\n']
    for i in range(linect):
        buffer.append('<li>%s</li>\n' % get_word())
    buffer.append('</ul>')
    return ''.join(buffer)


def build_ul_stringio(linect, get_word=get_8x):
    buffer = StringIO()
    buffer.write('<ul>\n')
    for i in range(linect):
        buffer.write('<li>%s</li>\n' % get_word())
    buffer.write('</ul>')
    return buffer.getvalue()


def build_ul_concat(linect, get_word=get_8x):
    buffer = '<ul>\n'
    for i in range(linect):
        buffer += ('<li>%s</li>\n' % get_word())
    buffer += '</ul>'
    return buffer
3
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?