コードやログの表示で読みやすさが大きく変わるため、Pythonでは文字列フォーマットがとても重要です。
本記事では昔ながらの2つの方法(パーセント演算子とstr.formatメソッド)に絞り、基礎から実践まで丁寧に解説します。
始めやすい書き方から幅や精度、整列、進数、エラー対処まで順を追って学べます。
Pythonの文字列フォーマットの基礎(%演算子とformatメソッド)
文字列フォーマットとは
文字列フォーマットとは、プレースホルダに値を差し込み、見やすく整形した文字列を作る仕組みです。
ログ出力、数値の丸め、表形式のレイアウトなど、日常のプログラミングで頻繁に登場します。
本記事では%演算子とstr.formatを扱います(f文字列は別記事で解説しています)。
%演算子とformatメソッドの違い
%演算子はC言語由来の古典的な書式で、短く書けてシンプルです。
一方でformatメソッドは柔軟で、属性やキー参照、埋め文字や整列など拡張が豊富です。
以下の観点で使い分けます。
- 手短に整数や文字列を差し込むだけなら
%が簡潔です。 - 名前付きや再利用、複雑な整形が必要なら
str.formatが適します。 - 国際化やテンプレート性を重視する場合は
str.formatのほうが表現力があります。
フォーマット指定子の基本(幅・精度・整列)
幅や精度、整列は出力の見やすさを左右します。
両方式の代表的な指定は次のとおりです。
| 目的 | %演算子 | 例 | formatメソッド | 例 |
|---|---|---|---|---|
| 幅(最小文字数) | 数字 | %10s | 数字 | {:10s} |
| 左寄せ | - | %-10s | < | {:<10s} |
| 右寄せ | 既定 | %10s | >(既定) | {:>10s} |
| 中央寄せ | なし | — | ^ | {:^10s} |
| 0埋め | 0 | %06d | 0 | {:06d} |
| 精度(小数点/最大長) | .n | %.2f | .n | {:.2f} |
| 符号 | +, | %+d | +, | {:+d} |
精度は浮動小数点では小数点以下の桁数、文字列では最大文字数として機能します。
- 関連記事:文字列と数値の型を変換したい
- 関連記事:文字列幅を揃える – 0埋め・左寄せ・右寄せ・中央寄せ
%演算子の使い方
基本形(%s,%d,%f)
%sは文字列、%dは整数、%fは浮動小数点に使います。
# 基本的な差し込み
name = "Alice"
age = 23
score = 91.234
print("Name: %s" % name) # %s は任意のオブジェクトの文字列表現(str)を埋め込み
print("Age: %d" % age) # %d は整数
print("Score: %f" % score) # %f は浮動小数点(既定は小数点以下6桁)
print("Score(小数2桁): %.2f" % score)
Name: Alice
Age: 23
Score: 91.234000
Score(小数2桁): 91.23
複数値の埋め込み(タプル)
複数値はタプルで渡します。
user = ("Bob", 7)
print("User: %s, ID: %d" % user) # ("Bob", 7) が順に %s, %d に対応
User: Bob, ID: 7
- 関連記事:タプル(tuple)の基本的な使い方
名前付きプレースホルダ(%(name)s)
辞書を渡して名前で参照できます。
data = {"host": "localhost", "port": 5432}
print("DB=%(host)s, PORT=%(port)d" % data)
DB=localhost, PORT=5432
- 関連記事:辞書(dict)の基本的な使い方
幅・精度・0埋め・左寄せ
幅は桁揃えに役立ちます。
0埋めや左寄せも指定できます。
n = 42
pi = 3.14159
s = "cat"
print("[%10s]" % s) # 右寄せ(幅10)
print("[%-10s]" % s) # 左寄せ(幅10)
print("[%06d]" % n) # 0埋め(幅6) -> 000042
print("[%.3f]" % pi) # 小数3桁に丸め
print("[%.3s]" % "abcdef") # 文字列を最大3文字に制限
[ cat]
[cat ]
[000042]
[3.142]
[abc]
符号とスペース(+,-, )
+は正数にも符号を表示し、 (スペース)は正数に空白を付けます。
-は左寄せのフラグで符号指定ではありません。
print("[%+d] [% d] [%d]" % (7, 7, -7))
[+7] [ 7] [-7]
リテラルの%を出す(%%)
パーセント記号自体を表示するには%%を使います。
rate = 0.375
print("Progress: %.1f%%" % (rate * 100))
Progress: 37.5%
%rと%sの違い
%sはstr()、%rはrepr()を使います。
デバッグには%rが有用です。
text = 'He said "hi".'
none_val = None
print("%s | %r" % (text, text)) # %r はクォートやエスケープを可視化
print("%s | %r" % (none_val, none_val)) # None の表示比較
He said "hi". | 'He said "hi".'
None | None
数値書式(指数%e,16進%x)
指数表記や進数表記も可能です。
num = 12345.6789
value = 255
print("exp: %e" % num) # 指数(小文字)
print("EXP: %E" % num) # 指数(大文字)
print("hex: %x" % value) # 16進(小文字)
print("HEX: %X" % value) # 16進(大文字)
exp: 1.234568e+04
EXP: 1.234568E+04
hex: ff
HEX: FF
formatメソッドの使い方
基本形({}とstr.format)
中括弧{}がプレースホルダです。
型を自動判定して文字列化します。
msg = "Hello, {}. You have {} new messages.".format("Alice", 3)
print(msg)
Hello, Alice. You have 3 new messages.
位置引数と名前付き引数
位置や名前を明示できます。
自動番号と明示番号は混在不可です。
print("{0} scored {1}".format("Bob", 92)) # 位置引数を番号で参照
print("{name} scored {score}".format(name="Eve", score=88)) # 名前付き引数
# print("{} {1}".format("X", "Y")) # 混在はエラー(ValueError)
Bob scored 92
Eve scored 88
フィールド名の参照(属性・キー・インデックス)
ドットで属性、[]でキー/インデックスを参照できます。
class User:
def __init__(self, name): self.name = name
u = User("Kai")
data = {"x": 10, "y": 20}
arr = ["zero", "one"]
print("user={0.name}".format(u)) # 属性
print("point=({p[x]}, {p[y]})".format(p=data)) # 辞書キー
print("arr[1]={a[1]}".format(a=arr)) # リストのインデックス
user=Kai
point=(10, 20)
arr[1]=one
- 関連記事:クラスの属性とメソッドとは?
書式指定ミニ言語(:指定子)の基本
コロン:に続けてミニ言語で詳細指定を行います。
- 形:
{フィールド:埋め文字整列幅.精度型} - 例:
{:>10s}(右寄せ幅10)、{:.2f}(小数2桁)
整列記号は<(左)、>(右)、^(中央)です。
x = 3.14159
print("[{:10}]".format("cat")) # 既定は右寄せ
print("[{:<10}]".format("cat")) # 左寄せ
print("[{:^10}]".format("cat")) # 中央寄せ
print("{:.3f}".format(x)) # 小数3桁
[ cat]
[cat ]
[ cat ]
3.142
文字列の整列と幅・埋め文字(<,>,^)
任意の1文字を埋め文字にできます。
print("[{:*>8}]".format("42")) # '*'で右側に詰めて左を埋める
print("[{:_^8}]".format("OK")) # '_'で中央寄せの両側を埋める
[******42]
[___OK___]
数値の精度・符号・0埋め
符号や0埋めは読みやすさに直結します。
n = 42
neg = -42
pi = 3.14159
print("{:+d}".format(n)) # 正数にも+を表示
print("{: d}".format(n)) # 正数は先頭に空白
print("{:06d}".format(n)) # 0埋め(幅6)
print("{:.2f}".format(pi)) # 小数2桁
print("{:+.2f}".format(pi)) # 小数2桁かつ符号
print("{: .2f}".format(neg)) # 符号と空白(負はマイナス表示)
+42
42
000042
3.14
+3.14
-42.00
千区切り(,)とパーセント(%)
千区切り,や百分率%も組み込みです。
百分率は値を100倍して%を付けます。
num = 1234567.89
ratio = 0.375
print("{:,}".format(num)) # 1,234,567.89
print("{:.2%}".format(ratio)) # 37.50%
1,234,567.89
37.50%
進数変換(b,o,d,x,X)と指数(e,E)
2進や16進、指数表記が簡単です。
v = 255
x = 12345.6789
print("{:b}".format(v)) # 2進
print("{:o}".format(v)) # 8進
print("{:d}".format(v)) # 10進
print("{:x}".format(v)) # 16進(小文字)
print("{:X}".format(v)) # 16進(大文字)
print("{:e}".format(x)) # 指数(小文字)
print("{:E}".format(x)) # 指数(大文字)
11111111
377
255
ff
FF
1.234568e+04
1.234568E+04
ネストと再利用(番号・名前)
同じ値を何度も使ったり、精度を動的に指定できます。
name = "Mio"
pi = 3.14159265
# 同じ値の再利用
print("Hi {0}, again {0}!".format(name))
# 動的精度のネスト: {0:.{p}f} の p は名前付き引数
print("PI={0:.{p}f}".format(pi, p=4))
Hi Mio, again Mio!
PI=3.1416
選び方と注意点(%演算子 vs formatメソッド)
どちらを使うべきかの目安
短く済ませたい単純置換は%、柔軟な整形や再利用・名前参照はformatが向きます。
既存コードの流儀に合わせるのも実務で大切です。
よくあるエラー(TypeError,KeyError,ValueError)
指定子やフィールド名の不一致で例外が出ます。
以下は代表例です。
def show_error(fn):
try:
fn()
except Exception as e:
print(type(e).__name__, "-", e)
# 1) % 演算子: 指定子と値の不一致
show_error(lambda: print("%d" % "42")) # 文字列に %d は不可 -> TypeError
# 2) format: 存在しない名前
show_error(lambda: print("{name}".format(user="Ann"))) # name が無い -> KeyError
# 3) format: 自動番号と明示番号の混在
show_error(lambda: print("{} {1}".format("A", "B"))) # -> ValueError
TypeError - %d format: a number is required, not str
KeyError - 'name'
ValueError - cannot switch from automatic field numbering to manual field specification
型と指定子の不一致に注意
数値型に文字列指定子、文字列に数値指定子を使うとエラーです。
例えば%dや{:d}は整数専用、{:.2f}は数値専用です。
安全側に倒すなら%sや{}で受け、必要に応じて明示的にint()やfloat()に変換します。
s = "100"
# 明示変換してから数値書式を使う
print("{:05d}".format(int(s)))
print("%.2f" % float(s))
00100
100.00
可読性・メンテ性の比較
長い文や多くの値を差し込む場合、名前付きのformatは意図が読み取りやすいです。
翻訳対応でも並び順変更に強くなります。
# 名前付きで意味が明確
tpl = "User={name}, Role={role}, Active={active}"
print(tpl.format(name="Aya", role="admin", active=True))
User=Aya, Role=admin, Active=True
- 関連記事:f-string書式指定まとめ
パフォーマンスと互換性の観点
どちらもPython 3で広く使え、互換性に問題はありません。
性能差はケース依存で、I/O付近では誤差程度です。
可読性と保守性を優先し、既存コードのスタイルに合わせるのが現実的です。
大量連結が必要なら、そもそもjoinやバッファリングを検討します。
まとめ
パーセント演算子はシンプルで短く、formatメソッドは柔軟で表現力が高いという住み分けを押さえれば、状況に応じた最適なフォーマットが選べます。
幅や精度、整列、符号、0埋め、進数、千区切り、百分率などを必要に応じて使い分け、エラーになりやすい型と指定子の不一致に注意してください。
最終的にはプロジェクトの方針と可読性を基準に、一貫した書き方で整った出力を心がけると保守性が高まります。
