閉じる

【Python】 f-string(f文字列)の使い方: 基本から書式指定子まで

f-stringは、Pythonで文字列の中に変数や式を直接埋め込める便利な機能です。

本記事では、基本構文から書式指定子による細かな整形、日付や数値のフォーマット、デバッグやセキュリティの考え方まで、初心者の方でも段階的に理解できるよう丁寧に解説します。

f-stringとは

f-stringはPython 3.6以降で導入された文字列リテラルの一種で、先頭にfまたはFを付け、{}(中かっこ)の中にPythonの式を書けるのが特徴です。

式は実行時に評価され、その結果が文字列に埋め込まれます。

従来の%演算子やstr.formatと比べて、可読性と実行速度に優れ、数値や日付の整形も簡潔に記述できます。

f-stringの主な特長は次の通りです。

詳しいサンプルコードは次章以降で示します。

  • 文字列中の式埋め込みが簡潔で読みやすいこと
  • 書式指定子により数値や文字列の出力スタイルを細かく制御できること
  • デバッグ用途のvar=記法や変換フラグ!r !s !aが使えること
  • 既存のstr.formatと同等のフォーマットミニ言語が使えること

f-stringの基本構文と式埋め込み

基本の書き方と変数の埋め込み

文字列リテラルの先頭にfを付け、{}の中に変数名を書きます。

Python
# 基本のf-string(変数の埋め込み)
name = "Alice"
age = 20
score = 95.5

# 文字列中にそのまま変数を埋め込めます
message = f"{name}は{age}歳です。スコアは{score}です。"
print(message)
実行結果
Aliceは20歳です。スコアは95.5です。

式や関数呼び出しの埋め込み

{}の中には、単なる変数だけでなく、四則演算や関数・メソッドの呼び出しなど任意の式を書けます。

Python
# 任意の式や関数呼び出しを埋め込めます
def inc(x):
    return x + 1

age = 20
text = "python"
a, b = 2, 3

print(f"来年は{inc(age)}歳。{a}+{b}={a+b}、{text}の大文字は{text.upper()}。")
実行結果
来年は21歳。2+3=5、pythonの大文字はPYTHON。

中かっこを出力するエスケープ

{}自体を文字として出したい場合は、{{}}と書きます。

Python
# 中かっこを出力したいときは二重にする
user = "Bob"
print(f"{{user}} は文字としての中かっこで、{user} は変数の展開です。")
実行結果
{user} は文字としての中かっこで、Bob は変数の展開です。

属性とインデックスへのアクセス

オブジェクトの属性や、リスト・辞書の要素にも直接アクセスできます。

Python
# 属性・インデックス・辞書のキーアクセス
class User:
    def __init__(self, name):
        self.name = name

u = User("Carol")
nums = [10, 20, 30]
config = {"lang": "Python", "ver": 3.12}

print(f"ユーザー名: {u.name}")
print(f"2番目の要素: {nums[1]}")
# f-stringの{}内では通常の式が使えるので、辞書キーにはクォートを使えます
print(f"使用言語: {config['lang']} {config['ver']}")
実行結果
ユーザー名: Carol
2番目の要素: 20
使用言語: Python 3.12

複数行文字列でのf-string

トリプルクォートを使えば、複数行のテンプレートが書けます。

インデントを整えるにはtextwrap.dedentが便利です。

Python
# 複数行のf-stringとインデント整理
from textwrap import dedent

name = "Dora"
message = dedent(f"""\
    件名: お知らせ
    宛先: {name}

    これは複数行のf-stringの例です。
    改行やインデントもそのまま出力されます。
""")
print(message)
実行結果
件名: お知らせ
宛先: Dora

これは複数行のf-stringの例です。
改行やインデントもそのまま出力されます。

raw文字列とf-stringの併用

正規表現やWindowsパスなど、バックスラッシュを含む文字列ではraw文字列修飾子rを併用できます。

fr"..."またはrf"...“の順序はどちらでも同じです。

Python
# raw(f)文字列の併用。外側はraw、その中の式は通常のPython式として評価される点に注意
word = "cat"
pattern = fr"\b{word}\b"  # \bはrawでそのまま、{word}は式展開
path = r"C:\Users\Alice\Desktop"

print(f"正規表現パターン: {pattern}")
print(f"パス: {path}")

# 注意: {}内の式部分にはバックスラッシュは書けません(構文エラーになります)
# 例: f"{\n}" は不可
実行結果
正規表現パターン: \bcat\b
パス: C:\Users\Alice\Desktop

書式指定子の使い方と数値フォーマット

書式指定の基本 コロン 型 精度

{値:書式}:以降が書式指定子です。

よく使うパターンは型と精度の指定です。

Python
# 基本的な型と精度の指定
num = 12.3456
n = 255

print(f"小数点以下2桁: {num:.2f}")   # 型fで小数点以下2桁
print(f"10進: {n:d}, 16進: {n:x}, 16進(大文字): {n:X}")
実行結果
小数点以下2桁: 12.35
10進: 255, 16進: ff, 16進(大文字): FF

代表的な指定子の構造は次の通りです。

形式: [[fill]align][sign][#][0][width][,|_][.precision][type]

よく使う要素の概要を表にまとめます。

項目説明
typed, b, o, x, X, f, e, g, n, %数値の型や表現方式を指定します。文字列は通常type省略。
.precision.2, .3小数の桁数(数値)または最大文字数(文字列)を指定します。
width6, 08最小幅。足りない分は埋めます。0はゼロ埋めに便利。
align<, >, ^, =左寄せ、右寄せ、中央、符号の直後に詰める(=)。
sign+, -, 空白符号の出力方法を指定します。
##進数表現で接頭辞(0b, 0o, 0x)を付けます。
区切り, または _千位区切り。,はカンマ、_はアンダースコア。
nnロケールに応じた数値表記を行います。
%%値×100してパーセント表記。

幅とゼロ埋めで桁を揃える

桁を揃えたいときは幅とゼロ埋めを使います。

負数のときの符号位置にも注意します。

Python
# 幅とゼロ埋め
x = 42
m = -42

print(f"[{x:5d}] 右寄せ5幅")
print(f"[{x:05d}] ゼロ埋め5幅")
print(f"[{m:>6d}] 負数の右寄せ6幅(空白で埋める)")
print(f"[{m:=6d}] =は符号の直後に詰める(空白埋め)")
print(f"[{m:06d}] ゼロ埋めと=の組み合わせ(デフォルトで=相当)")
実行結果
[   42] 右寄せ5幅
[00042] ゼロ埋め5幅
[   -42] 負数の右寄せ6幅(空白で埋める)
[-   42] =は符号の直後に詰める(空白埋め)
[-00042] ゼロ埋めと=の組み合わせ(デフォルトで=相当)

小数点以下の桁数と丸め

小数はf型で桁数を指定できます。

浮動小数点の丸めには注意が必要です。

Python
# 小数点以下の桁数指定と丸め
pi = 3.14159
print(f"piを小数2桁: {pi:.2f}")

# 浮動小数点の表現上、期待と異なる丸めに見えることがあります
x = 2.675
print(f"2.675を小数2桁: {x:.2f}  (バイナリ表現の都合で2.67になることがあります)")

# 正確な丸めが必要ならDecimalを使います
from decimal import Decimal, ROUND_HALF_UP
dx = Decimal("2.675").quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
print(f"Decimalで四捨五入: {dx}")
実行結果
piを小数2桁: 3.14
2.675を小数2桁: 2.67  (バイナリ表現の都合で2.67になることがあります)
Decimalで四捨五入: 2.68

桁区切りとロケール対応

カンマ区切りやアンダースコア区切り、ロケール(地域設定)に応じた表記ができます。

Python
# 千位区切り
n = 1234567.89
print(f"カンマ区切り: {n:,}")
print(f"アンダースコア区切り: {n:_}")

# ロケール依存の区切り(n) - 実際の出力は環境によって異なります
import locale
try:
    locale.setlocale(locale.LC_ALL, "ja_JP.UTF-8")  # 利用不可ならexceptへ
except locale.Error:
    locale.setlocale(locale.LC_ALL, "")  # システム既定にフォールバック

print(f"ロケール依存の表記: {n:n}")
実行結果
カンマ区切り: 1,234,567.89
アンダースコア区切り: 1_234_567.89
ロケール依存の表記: 1,234,567.89

注: nの見た目は環境のロケール設定に依存します。

符号と整列の制御

符号の出力方法や配置を細かく制御できます。

Python
# 符号の制御
pos, neg = 42, -42
print(f"+を常に表示: {pos:+d}, {neg:+d}")
print(f"負のみ符号: {pos:-d}, {neg:-d}")  # デフォルト
print(f"正を空白:  [{pos: d}], [{neg: d}]")

# 整列(幅6)
print(f"右寄せ:   [{pos:>6d}]")
print(f"左寄せ:   [{pos:<6d}]")
print(f"中央寄せ: [{pos:^6d}]")
実行結果
+を常に表示: +42, -42
負のみ符号: 42, -42
正を空白:  [ 42], [-42]
右寄せ:   [    42]
左寄せ:   [42    ]
中央寄せ: [  42  ]

進数表現 2進 8進 16進

b(2進), o(8進), x/X(16進)を使います。

#で接頭辞を付けられます。

Python
n = 255
print(f"2進:{n:b}  8進:{n:o}  16進:{n:x}  16進(大):{n:X}")
print(f"接頭辞あり: 2進:{n:#b}  8進:{n:#o}  16進:{n:#x}")
実行結果
2進:11111111  8進:377  16進:ff  16進(大):FF
接頭辞あり: 2進:0b11111111  8進:0o377  16進:0xff

パーセントと指数表記

割合は%、指数はe/Eg/Gが使えます。

Python
ratio = 0.12345
big = 123456

print(f"割合(小数1桁): {ratio:.1%}")
print(f"指数表記: {big:.2e}")
print(f"最適桁数(g): {big:.3g}")
実行結果
割合(小数1桁): 12.3%
指数表記: 1.23e+05
最適桁数(g): 1.23e+05

日付と時刻のフォーマット

datetimestrftime風の指定をそのまま使えます。

Python
from datetime import datetime

dt = datetime(2025, 1, 2, 15, 4, 5)
print(f"ISO風: {dt:%Y-%m-%d %H:%M:%S}")
print(f"月/日: {dt:%m/%d}  曜日: {dt:%a}")
print(f"ロケール依存の日時(%c): {dt:%c}")  # 出力は環境依存
実行結果
ISO風: 2025-01-02 15:04:05
月/日: 01/02  曜日: Thu
ロケール依存の日時(%c): Thu Jan  2 15:04:05 2025

文字列の長さ制限と切り詰め

文字列に対して.precisionを付けると最大長を制限できます。

Python
s = "こんにちはPython"
print(f"先頭5文字だけ: [{s:.5}]")
print(f"幅10で右寄せしつつ先頭5文字: [{s:>10.5}]")
実行結果
先頭5文字だけ: [こんにちは]
幅10で右寄せしつつ先頭5文字: [     こんにちは]

応用テクニックとベストプラクティス

変換フラグ !r !s !a の使い分け

!sstr()!rrepr()!aascii()での表示を使います。

Python
class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y
    def __str__(self):
        return f"Point({self.x}, {self.y})"     # 人向け
    def __repr__(self):
        return f"Point(x={self.x!r}, y={self.y!r})"  # 開発者向け

p = Point(1, 2)
print(f"!s: {p!s}")
print(f"!r: {p!r}")
print(f"!a: {"日本語"!a}")  # 非ASCIIをエスケープして表示
実行結果
!s: Point(1, 2)
!r: Point(x=1, y=2)
!a: '\u65e5\u672c\u8a9e'

デバッグ出力 var= の活用

Python 3.8以降は{変数名=}で「名前=値」の形を自動で出力できます。

書式指定も併用できます。

Python
x = 10
y = 3.14159
print(f"{x=}, {y=:.2f}")
print(f"{x+1=}, {y*2=:.3f}")  # 式=値 の形も可
実行結果
x=10, y=3.14
x+1=11, y*2=6.283

条件式や三項演算子の活用

{}内に条件式を書いて、表示内容を切り替えられます。

Python
score = 72
count1, count2 = 1, 2

print(f"判定: {'合格' if score >= 70 else '不合格'}")
print(f"{count1} item{'s' if count1 != 1 else ''}")
print(f"{count2} item{'s' if count2 != 1 else ''}")
実行結果
判定: 合格
1 item
2 items

セキュリティとユーザー入力の扱い

f-stringは便利ですが、外部入力を埋め込む先がSQLやシェルの場合は注入攻撃に注意が必要です。

Python
# 悪い例: SQL文字列をf-stringで生成 (SQLインジェクションの危険)
user_id = "1 OR 1=1"
query_bad = f"SELECT * FROM users WHERE id = {user_id};"

# 良い例: パラメータ化クエリを使う (DBAPIに合わせてプレースホルダは変わります)
# SQLiteなら?、psycopgなら%sなど
import sqlite3
conn = sqlite3.connect(":memory:")
cur = conn.cursor()
cur.execute("CREATE TABLE users(id INTEGER, name TEXT)")
cur.execute("INSERT INTO users VALUES(?, ?)", (1, "Alice"))

safe_id = 1
cur.execute("SELECT * FROM users WHERE id = ?", (safe_id,))
print(cur.fetchone())
conn.close()
実行結果
(1, 'Alice')
  • シェル実行はsubprocess.run([...])の引数リストで渡し、shell=Trueとf-string連結を避けます。
  • HTMLへの埋め込みはhtml.escapeでエスケープし、テンプレートエンジンの自動エスケープを活用します。
  • 秘密情報(トークンやパスワード)をf-stringでログに出力しないように注意します。

パフォーマンスと可読性の指針

  • f-stringは通常、%str.formatより高速かつ簡潔です。特に多数の小さな結合では有利です。
  • 大量の文字列をループで連結する場合は、各行をf-stringで作ってリストに貯め、最後に"".join(list)でまとめると効率的です。
  • ログはlogger.debug("x=%s", x)のように遅延フォーマットを使うと、無効時のフォーマットコストを回避できます。
  • {}内の式は短く保ち、計算は事前に変数へ分離すると読みやすくなります。
Python
# 大量生成のときの指針: ループ内で直接足し合わせず、joinを使う
rows = []
for i in range(5):
    rows.append(f"行{i}: 値={i*i}\n")
result = "".join(rows)
print(result)
実行結果
行0: 値=0
行1: 値=1
行2: 値=4
行3: 値=9
行4: 値=16

よくあるエラーとトラブルシューティング

  • f-string: expecting ‘}’ または unmatched ‘{‘
    中かっこが閉じていない、あるいは余分です。{{}}でのエスケープを忘れていないか確認します。
  • f-string expression part cannot include a backslash
    {}内の式にバックスラッシュは書けません。必要なら式外にするか、raw文字列を使うなどの設計にします。
  • TypeError: unknown format code ‘d’ for object of type ‘str’
    文字列に整数用のdを適用しています。int(s)に変換するか、型に合った指定子を選びます。
  • ValueError: Invalid format specifier / 不正な書式指定
    スペルや順序、組み合わせを確認します。例えば:,_.2fのような不正な組み合わせは不可です。
  • NameError: name ‘x’ is not defined
    {}内の変数がスコープに存在しません。スペルとスコープを確認します。
  • raw文字列で最後が\
    raw文字列は末尾に単独の\を置けません。"\\ "とするか設計を見直します。
  • ロケールnの見た目が想定と違う
    locale.setlocaleの設定と実行環境のロケールが影響します。環境依存であることに留意してください。

まとめ

本記事では、f-stringの基本から書式指定子による高度な整形、日付・時刻や進数表現、!r !s !avar=によるデバッグ、raw文字列や複数行テンプレート、さらにセキュリティ・パフォーマンスの注意点まで幅広く解説しました。

ポイントは次の通りです。

f-stringは{}内に式を書くだけで直感的に使え、:{書式}で幅や桁数、整列、区切り、型などを柔軟に制御できます。

ログやSQL・シェルの組み立てでは安全な方法(パラメータ化、遅延フォーマット)を選び、可読性のために式は短く保つと良いです。

ここで紹介したパターンを覚えておけば、実務での文字列整形が確実にスムーズになります。

ぜひ手元のコードに取り入れて、簡潔で読みやすい出力を実現してください。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!