Pythonで文字列・数値を右寄せ・左寄せ・中央寄せする方法|f文字列とljust・rjust・center

Python で文字列を左寄せ・右寄せ・中央寄せするには、f文字列の書式指定で f"{s:<10}"(左)、f"{s:>10}"(右)、f"{s:^10}"(中央)と書くか、文字列メソッドの ljust()・rjust()・center() を使います。数値のゼロ埋めは f"{n:08}" か zfill() です。

この記事では、公式ドキュメントの書式指定ミニ言語とstr のメソッドの仕様に沿って、それぞれの書き方、数値の扱い、幅を変数で指定する方法、表の整形、日本語(全角文字)で列がずれる問題の対処を、実行結果つきで説明します。コードは Python 3.9.6 で実行しました。

早見表

やりたいことf文字列・format文字列メソッド
左寄せf"{s:<10}"s.ljust(10)
右寄せf"{s:>10}"s.rjust(10)
中央寄せf"{s:^10}"s.center(10)
埋め文字を変えるf"{s:-^10}"s.center(10, "-")
数値のゼロ埋めf"{n:08}"str(n).zfill(8)
幅を変数でf"{s:>{w}}"s.rjust(w)

f文字列で寄せる(< > ^)

f文字列の {} の中で、コロンの後に「寄せる向き」と「幅」を書きます。< が左、> が右、^ が中央です。結果が分かりやすいように [ ] で囲んで表示します。

s = "Python"
print(f"[{s:<10}]")   # 左寄せ
print(f"[{s:>10}]")   # 右寄せ
print(f"[{s:^10}]")   # 中央寄せ

実行結果:

[Python    ]
[    Python]
[  Python  ]

幅10に対して “Python” は6文字なので、残り4文字分が空白で埋まります。同じ書き方は "{:>10}".format(s) のように format() メソッドでも使えます。

数値と文字列で既定の向きが違う

向きを書かずに幅だけ指定すると、公式ドキュメントのとおり数値は右寄せ、文字列などは左寄せになります。埋め文字を変えるときは、向きの記号の直前に1文字書きます。

n = 42
print(f"[{n:10}]")     # 数値は指定しなければ右寄せ
print(f"[{'42':10}]")  # 文字列は指定しなければ左寄せ
print(f"[{n:<10}]")
print(f"[{n:-^10}]")   # 埋め文字は記号の前に書く

実行結果:

[        42]
[42        ]
[42        ]
[----42----]

ljust・rjust・center メソッドで寄せる

文字列メソッドでも同じことができます。第2引数で埋め文字を1文字指定できます。

s = "Python"
print("[" + s.ljust(10) + "]")
print("[" + s.rjust(10) + "]")
print("[" + s.center(10) + "]")
print("[" + s.center(10, "-") + "]")
print("[" + "Monty Python".ljust(5) + "]")   # 幅より長いときはそのまま

実行結果:

[Python    ]
[    Python]
[  Python  ]
[--Python--]
[Monty Python]

最後の行のように、指定した幅より文字列が長いときは切り詰められず、そのまま返ります(f文字列でも同じです)。表示幅を必ずそろえたいなら、先にスライスで切っておく必要があります。

ljust などは文字列にしか使えないので、数値は str(n).rjust(8) のように文字列に変換してから呼びます。数値の書式(桁区切りや小数の桁数)も一緒に指定したいなら、f文字列の方が一度で書けます。

中央寄せで余りが出るとき

余白が奇数になると、どちらかの側が1文字多くなります。center() と f文字列の ^ では、その1文字がどちらに付くかが一致しない場合があります。

s = "Python"   # 6文字。幅11だと余白は5で割り切れない
print("[" + s.center(11, "-") + "]")
print(f"[{s:-^11}]")
s = "Hello"    # 5文字。幅10だと余白は5
print("[" + s.center(10, "-") + "]")
print(f"[{s:-^10}]")

実行結果:

[---Python--]
[--Python---]
[--Hello---]
[--Hello---]

見た目を厳密にそろえたい場面では、どちらか一方の書き方に統一しておくと安全です。

数値のゼロ埋めと符号

ゼロ埋めでよくある間違いが、負の数を > で埋めてしまうことです。>08 だと符号の前に 0 が入り、「00000-42」になります。幅の直前に 0 を書く 08 か、向きに = を指定すると、符号の後ろが埋まります。

n = -42
print(f"[{n:>08}]")   # 右寄せのゼロ埋め:符号の前に0が入る
print(f"[{n:08}]")    # 0 を幅の直前に書くと符号の後ろを埋める(= と同じ)
print(f"[{n:=8}]")
print("-42".zfill(8))
print("7".zfill(3))

実行結果:

[00000-42]
[-0000042]
[-     42]
-0000042
007

zfill() も符号を考慮して、符号の後ろに 0 を入れます。ID や日付の「007」「09」のような表示によく使います。

小数点と桁区切りをそろえて右寄せ

金額や計測値を縦にそろえるときは、右寄せに桁区切り(,)と小数の桁数(.1f など)を組み合わせます。小数点の位置がそろうので読みやすくなります。

prices = [1500, 250, 12000, 980.5]
for p in prices:
    print(f"{p:>10,.1f}")

実行結果:

   1,500.0
     250.0
  12,000.0
     980.5

幅や向きを変数で指定する

列の幅をデータに合わせて決めたいときは、書式指定の中にさらに {} を入れて変数を使えます。

width = 12
for word in ["apple", "banana", "kiwi"]:
    print(f"[{word:>{width}}]")

align = "^"
print(f"[{'center':{align}{width}}]")
print("[{:{}{}}]".format("format", "<", width))

実行結果:

[       apple]
[      banana]
[        kiwi]
[   center   ]
[format      ]

表の形に整えて出力する

文字列の列は左寄せ、数値の列は右寄せにするのが表の基本です。見出しも同じ幅で寄せると列がそろいます。

rows = [("apple", 150, 3), ("banana", 200, 2), ("orange", 1200, 10)]
print(f"{'item':<8}{'price':>7}{'qty':>5}{'total':>8}")
print("-" * 28)
for name, price, qty in rows:
    print(f"{name:<8}{price:>7,}{qty:>5}{price * qty:>8,}")

実行結果:

item      price  qty   total
----------------------------
apple       150    3     450
banana      200    2     400
orange    1,200   10  12,000

日本語(全角文字)で列がずれる理由と対処

f文字列も ljust も、幅を「文字数」で数えます。ところが端末やテキストエディタでは、多くの場合ひらがなや漢字は半角の2文字分の幅で表示されます。そのため、日本語を含むと見た目がずれます。

for s in ["Python", "パイソン"]:
    print(f"[{s:>10}]", len(s))

実行結果:

[    Python] 6
[      パイソン] 4

“パイソン” は4文字なので空白が6つ入りますが、表示上は8文字分の幅があるため、右端がそろいません。

unicodedata で表示幅を数える

標準ライブラリの unicodedata.east_asian_width() は、文字ごとの東アジアの文字幅の区分を返します。区分が W(全角)と F(全角英数など)の文字を2、それ以外を1として数えれば、多くの環境で見た目に近い幅になります。

import unicodedata

def text_width(s):
    """東アジアの文字幅が W・F の文字を2、それ以外を1として数える"""
    return sum(2 if unicodedata.east_asian_width(c) in "WF" else 1 for c in s)

def ljust_w(s, width, fill=" "):
    return s + fill * max(0, width - text_width(s))

def rjust_w(s, width, fill=" "):
    return fill * max(0, width - text_width(s)) + s

rows = [("りんご", 150), ("バナナ", 200), ("orange", 1200)]
for name, price in rows:
    print("[" + ljust_w(name, 10) + "]" + "[" + rjust_w(f"{price:,}", 7) + "]")

実行結果:

[りんご    ][    150]
[バナナ    ][    200]
[orange    ][  1,200]

この方法にも限界があります。区分が A(曖昧)の記号(○や①など)は環境によって1幅にも2幅にもなり、絵文字も端末によって幅が変わります。表示を完全にそろえたいなら、CSV や Excel など列を持つ形式で出力するか、HTML の表にするのが確実です。

使い分けの目安

書き方向いている場面
f文字列(Python 3.6 以降)ほとんどの場面。数値の書式と寄せを一度に書ける
format() メソッド書式の文字列を先に用意して、あとから値を入れたいとき
ljust / rjust / center文字列だけを寄せたいとき。埋め文字の指定も分かりやすい
zfill数字の文字列を0で埋めたいとき

よくある質問

Q. Python で文字列を右寄せするには?

f”{s:>10}” のように、コロンの後に > と幅を書きます。文字列メソッドなら s.rjust(10) です。どちらも幅に足りない分を左側に空白で埋めます。

Q. 数値を0埋めで右寄せするには?

f”{n:08}” と書くか、str(n).zfill(8) を使います。f”{n:>08}” と書くと負の数で符号の前に0が入るので注意してください。

Q. ljust で指定した幅より長い文字列はどうなりますか?

切り詰められず、元の文字列がそのまま返ります。f文字列の書式指定でも同じです。幅を超えないようにしたいときは、先にスライスで切っておきます。

Q. 日本語を含むと列がずれるのはなぜですか?

f文字列や ljust は幅を文字数で数えますが、多くの端末では全角文字が半角2文字分の幅で表示されるからです。unicodedata.east_asian_width() で表示幅を数えて空白を足すと、多くの環境でそろいます。

Q. 中央寄せで余りが出たら、どちらに空白が付きますか?

余白が奇数のとき、center() と f文字列の ^ では余った1文字の付く側が一致しない場合があります。見た目を厳密にそろえたい場合は、どちらか一方の書き方に統一してください。

まとめ

  • 左寄せは <、右寄せは >、中央寄せは ^。メソッドなら ljust・rjust・center
  • 幅だけ書くと、数値は右寄せ、文字列は左寄せになる
  • 負の数のゼロ埋めは 08 か = を使い、>08 は避ける
  • 幅は {w} のように変数で指定できる
  • 日本語を含む表は、表示幅を数える関数で空白を足す

書式指定は覚える記号が多いので、早見表を手元に置いて試しながら覚えるのが近道です。基礎から一通り学びたい人は、テックジムの無料講座から始めてみてください。

あわせて読みたい

学習の順序はPython学習のロードマップ、標準で使える機能の一覧はPython標準ライブラリのモジュール一覧にまとめています。

Pythonの関数・メソッドの全体像はPython基本関数・メソッド完全一覧にまとめています。

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら