Pythonのf-stringは、コードを簡潔かつ読みやすく書けるとても便利な機能です。
従来のformat()や%演算子に比べて、変数や式を直感的に埋め込めるため、ログ出力やデバッグ、整形表示などさまざまな場面で活躍します。
本記事では、f-stringの基本から実務で役立つテクニック、注意点までを、サンプルコードと図解を交えながら詳しく解説します。
f-stringとは?Pythonの基本文法をおさらい
f-stringとは何か

f-stringとは、Python 3.6以降で導入されたフォーマット済み文字列リテラルのことで、文字列の前にfまたはFを付けて書きます。
文字列の中で{}(波かっこ)を使うことで、変数や式の値をその場で展開できます。
従来は"{} {}".format(x, y)や"%s %d" % (name, age)のように記述していたものを、f-stringではf"{name} {age}"と直接書けます。
これにより、コードの可読性が大きく向上し、バグも減らしやすくなります。
f-stringの基本構文と書き方

f-stringの基本構文は次の形です。
- 先頭に
fまたはFを付ける - 文字列リテラルの中に
{式}を書く - 必要に応じて
{式:フォーマット指定}のように書式指定子を付ける
もっとも基本的な例
name = "Alice"
age = 20
# 変数をそのまま埋め込む
message = f"名前は{name}、年齢は{age}歳です。"
print(message)
名前はAlice、年齢は20歳です。
式を直接書く例
price = 1200
tax_rate = 0.1
# f-stringの中で式をそのまま計算できる
message = f"税込価格は{price * (1 + tax_rate)}円です。"
print(message)
税込価格は1320.0円です。
このように、f-string内の{}には「式」をそのまま書くことができます。
変数だけでなく、関数呼び出しやメソッド呼び出し、演算なども記述可能です。
Pythonの対応バージョンと注意点

f-stringはPython 3.6以降で使えます。
Python 3.5以前では構文エラーになるため、レガシー環境を対象にする場合は注意が必要です。
また、Python 3.8以降ではデバッグ用の=構文が追加されるなど、バージョンごとに機能差があります。
簡単に表で整理すると次のようになります。
| Pythonバージョン | f-string利用可否 | 特記事項 |
|---|---|---|
| 3.5以前 | 利用不可 | 実行するとSyntaxError |
| 3.6〜3.7 | 利用可能 | 基本的なf-string機能が使用可能 |
| 3.8以降 | 利用可能 | f"{var=}"などデバッグ表示が追加 |
ライブラリやツールのサポート対象バージョンを確認し、f-stringが使える前提かどうかを事前に把握しておくと安心です。
f-stringの便利な使い方
変数・式を埋め込む基本テクニック

変数や式を埋め込む基本は「f"...{式}..."」という形です。
ここでの「式」には、変数、演算、関数呼び出し、メソッド呼び出しなど、Pythonで評価できるあらゆるものを使えます。
変数を複数埋め込む
first_name = "Taro"
last_name = "Yamada"
age = 30
profile = f"{last_name} {first_name} さんは {age} 歳です。"
print(profile)
Yamada Taro さんは 30 歳です。
メソッドや関数の呼び出しを埋め込む
text = "hello"
numbers = [1, 2, 3]
# upper()などのメソッドもそのまま書ける
message = f"{text.upper()}! 要素数は {len(numbers)} 個です。"
print(message)
HELLO! 要素数は 3 個です。
このように、中間変数をわざわざ用意しなくても、その場で処理結果を文字列化できるのが大きな利点です。
数値フォーマット

f-stringでは、{値:フォーマット指定}という形で、数値の表示形式を細かく制御できます。
これは従来のformat()関数と同じ仕様を持ちます。
代表的な指定を表で整理します。
| 目的 | 書式指定 | 例(値=1234.567) | 結果 |
|---|---|---|---|
| 小数点以下の桁数指定 | .2f | {value:.2f} | 1234.57 |
| 3桁ごとのカンマ区切り | , | {value:,} | 1,234.567 |
| カンマ+小数桁数 | ,.2f | {value:,.2f} | 1,234.57 |
| ゼロ埋め(幅6) | 06 | {42:06} | 000042 |
| パーセント表示 | .1% | {0.256:.1%} | 25.6% |
実際のコード例
value = 1234.567
ratio = 0.256
count = 42
print(f"小数点以下2桁: {value:.2f}")
print(f"3桁区切り: {value:,}")
print(f"3桁区切り+2桁: {value:,.2f}")
print(f"ゼロ埋め6桁: {count:06}")
print(f"パーセント表示: {ratio:.1%}")
小数点以下2桁: 1234.57
3桁区切り: 1,234.567
3桁区切り+2桁: 1,234.57
ゼロ埋め6桁: 000042
パーセント表示: 25.6%
数値フォーマットの指定は、後述する金額やテーブル出力でも頻繁に使う重要ポイントです。
日付と時刻のフォーマット

日付や時刻を扱う際は、datetimeオブジェクトに%Y-%m-%dのようなフォーマットを指定して表示します。
f-stringでは、{dt:%Y-%m-%d}という形で直接書けます。
代表的な日付フォーマット
from datetime import datetime
now = datetime(2024, 5, 1, 14, 30, 45)
print(f"ISO形式: {now:%Y-%m-%dT%H:%M:%S}")
print(f"日付だけ: {now:%Y/%m/%d}")
print(f"時刻だけ: {now:%H:%M}")
print(f"和風表記: {now:%Y年%m月%d日(%a) %H時%M分}")
ISO形式: 2024-05-01T14:30:45
日付だけ: 2024/05/01
時刻だけ: 14:30
和風表記: 2024年05月01日(Wed) 14時30分
よく使う書式記号を簡単にまとめます。
| 記号 | 意味 | 例 |
|---|---|---|
| %Y | 西暦4桁 | 2024 |
| %m | 月(ゼロ埋め2桁) | 05 |
| %d | 日(ゼロ埋め2桁) | 01 |
| %H | 時(24時間) | 14 |
| %M | 分 | 30 |
| %S | 秒 | 45 |
| %a | 曜日(短縮) | Wed |
ログ出力やレポート生成など、日付時刻は実務で頻出ですので、f-stringとセットで覚えておくと効率が上がります。
f-stringで改行やタブを含める方法

f-stringの中でも、通常の文字列と同様に\n(改行)や\t(タブ)などのエスケープシーケンスを使えます。
改行やタブを含む例
name = "Alice"
score_math = 80
score_english = 92
report = (
f"受験者: {name}\n"
f"\t数学: {score_math}\n"
f"\t英語: {score_english}"
)
print(report)
受験者: Alice
数学: 80
英語: 92
複数行にわたる文字列を扱う場合、上記のように()で囲んで複数のf-stringを連結するとインデントを保ちつつ可読性の高いコードを書けます。
ネストした式や関数呼び出しの活用例

f-string内では、単純な変数参照だけでなく、少し複雑な式や関数呼び出しも書けます。
ただし、あまり複雑にしすぎると読みづらくなるため、適度なバランスが重要です。
税込価格と割引価格を同時に計算する例
price = 1200
tax_rate = 0.1
discount_rate = 0.2
message = (
f"元の価格: {price}円\n"
f"税込価格: {price * (1 + tax_rate):.0f}円\n"
f"割引後税込: {price * (1 - discount_rate) * (1 + tax_rate):.0f}円"
)
print(message)
元の価格: 1200円
税込価格: 1320円
割引後税込: 1060円
関数を使って読みやすくする例
def tax_included(price, tax_rate=0.1):
return int(price * (1 + tax_rate))
price = 1200
message = (
f"元の価格: {price}円\n"
f"税込価格: {tax_included(price)}円"
)
print(message)
元の価格: 1200円
税込価格: 1320円
このように、ロジックを関数に切り出してからf-stringに埋め込むと、コード全体がすっきりします。
デバッグに便利なf-string

Python 3.8以降では、デバッグ用途に便利なf"{変数=}"構文が使えます。
変数名と値をまとめて表示してくれるため、printデバッグが非常に楽になります。
デバッグ出力の例
x = 10
y = 3
# 3.8以降で使える構文
print(f"{x=}")
print(f"{y=}")
print(f"{x + y=}")
x=10
y=3
x + y=13
式そのものx + yと結果が対になって出力されるので、どの計算結果なのかが一目で分かります。
ログや一時的なデバッグで非常に重宝します。
f-stringの注意点とハマりどころ
クォート(引用符)と波かっこ(中かっこ)のエスケープ方法

f-stringでよくつまずくのが、クォート文字や波かっこ{}を文字として表示したい場合です。
クォートの扱い
文字列リテラルを"..."で囲む場合、内部で"を使うときはエスケープするか、外側を'...'に変える必要があります。
name = "Alice"
# 外側をダブルクォート、内側をシングルクォートにする例
msg1 = f'"{name}" さんがログインしました。'
print(msg1)
# 外側をシングルクォート、内側をダブルクォートにする例
msg2 = f'"{name}" has logged in.'
print(msg2)
"Alice" さんがログインしました。
"Alice" has logged in.
両方同じクォートを使いたい場合は、バックスラッシュでエスケープします。
name = "Alice"
msg = f"\"{name}\" さんがログインしました。"
print(msg)
"Alice" さんがログインしました。
波かっこ{}を文字として出したい場合
f-stringでは{と}は式の区切りに使われます。
そのため、文字として{や}を出力したいときは2つ続けて書きます。
# 中かっこをそのまま表示したい
text = f"この辞書は {{'key': 'value'}} のような形です。"
print(text)
この辞書は {'key': 'value'} のような形です。
{と}のエスケープ忘れは頻出のSyntaxError原因なので注意してください。
辞書・リストを埋め込むときの注意点

辞書やリストの要素をf-stringに埋め込む場合、クォートの入れ子に注意が必要です。
クォートがぶつかってしまう悪い例
user = {"name": "Alice", "age": 20}
# これはSyntaxErrorになる例
# msg = f"ユーザー名: {user["name"]}、年齢: {user["age"]}"
上記は、外側と内側のクォートが両方ダブルクォートのため文法的に壊れてしまいます。
クォートを使い分ける正しい例
user = {"name": "Alice", "age": 20}
# 外側をダブルクォート、内側をシングルクォートにする
msg = f"ユーザー名: {user['name']}、年齢: {user['age']}"
print(msg)
ユーザー名: Alice、年齢: 20
あるいは、事前に変数に取り出してから埋め込むとより安全です。
user = {"name": "Alice", "age": 20}
name = user["name"]
age = user["age"]
msg = f"ユーザー名: {name}、年齢: {age}"
print(msg)
ユーザー名: Alice、年齢: 20
ネストが深くなったり、キー名が長くなってきたら、無理にf-string内にすべて書かず、変数に取り出してから使うと読みやすくなります。
日本語・全角文字を含む場合のフォーマット注意

日本語などの全角文字を含んだ文字列を、f-stringで列揃えしようとしたときに見かけ上の幅が合わないという問題がよく起こります。
Pythonの文字列幅指定{text:10}は「文字数」ベースであり、全角1文字も半角1文字も同じ1として扱われるためです。
全角を含む列揃えがずれる例
items = [
("Apple", 120),
("バナナ", 80),
("みかん", 100),
]
for name, price in items:
# 10文字幅で左寄せ、5文字幅で右寄せ
print(f"{name:10} : {price:5}円")
Apple : 120円
バナナ : 80円
みかん : 100円
見た目では、日本語の行がずれて見えることがあります。
これはターミナル側の全角幅の扱いやフォントにも依存します。
Python標準のフォーマットだけでは、見かけ上の幅を完全に揃えることは難しいため、厳密な整列が必要であればunicodedataモジュールで幅を計算したり、サードパーティライブラリ(例えばwcwidth)を使うことも検討してください。
セキュリティ

f-stringそのものは安全な機能ですが、ユーザー入力をf-stringの中で「式」として評価するような使い方をすると非常に危険です。
絶対に避けるべきパターンのイメージ
# 危険な例(あくまでイメージ。実際に真似しないこと)
user_expr = input("式を入力してください: ")
# f-stringを使ってeval的なことをしてしまう
# result = eval(f"{user_expr}")
上記のように、外部からの入力をそのままPythonコードとして評価するのは、f-stringに限らず重大なセキュリティリスクになります。
ログや画面表示など、「単に値を埋め込んで表示する」用途であれば安全ですが、「文字列をコードとして評価する」用途にf-stringを絡めてはいけません。
長いf-string・複数行f-stringの可読性問題

f-stringは便利な反面、1つのf-stringに多くの式や長い文を詰め込み過ぎると、途端に読みづらくなります。
悪い例(1行が長すぎる)
# コメント: これはあえて読みにくい例です
user = {"name": "Alice", "age": 20, "score": 92}
print(f"ユーザー名: {user['name']}、年齢: {user['age']}、評価: {'合格' if user['score'] >= 80 else '不合格'}、スコア(偏差値換算): {(user['score'] - 50) / 10 * 15:.1f}")
このような1行は、後から読むと非常に負担が大きくなります。
良い例(分割+変数の活用)
user = {"name": "Alice", "age": 20, "score": 92}
name = user["name"]
age = user["age"]
score = user["score"]
status = "合格" if score >= 80 else "不合格"
deviation = (score - 50) / 10 * 15
message = (
f"ユーザー名: {name}、"
f"年齢: {age}、"
f"評価: {status}、"
f"スコア(偏差値換算): {deviation:.1f}"
)
print(message)
ユーザー名: Alice、年齢: 20、評価: 合格、スコア(偏差値換算): 63.0
「式が複雑になったら変数に分ける」「1行が長くなったら複数行に分ける」という2つのルールを意識すると、f-stringの可読性を高く保てます。
f-string実例集
四則演算と文字列連結の実例

f-stringを使うと、四則演算の式と結果を自然な文章で表現できます。
a = 10
b = 3
result = (
f"{a} + {b} = {a + b}\n"
f"{a} - {b} = {a - b}\n"
f"{a} * {b} = {a * b}\n"
f"{a} / {b} = {a / b:.2f}"
)
print(result)
10 + 3 = 13
10 - 3 = 7
10 * 3 = 30
10 / 3 = 3.33
従来であればstr(a) + " + " + str(b) + " = " + str(a + b)のように書く必要がありましたが、f-stringでは非常にすっきりと記述できます。
金額やパーセント表示の実例

実務でよくある「金額」や「割合」の表示を、f-stringで分かりやすく整形してみます。
price = 1234567
tax_rate = 0.1
discount_rate = 0.15
tax_amount = int(price * tax_rate)
discount_amount = int(price * discount_rate)
final_price = price + tax_amount - discount_amount
receipt = (
f"小計: {price:>12,} 円\n"
f"消費税({tax_rate:.0%}): {tax_amount:>8,} 円\n"
f"値引き({discount_rate:.0%}): -{discount_amount:>7,} 円\n"
f"{'-' * 30}\n"
f"合計: {final_price:>12,} 円"
)
print(receipt)
小計: 1,234,567 円
消費税(10%): 123,456 円
値引き(15%): -185,184 円
------------------------------
合計: 1,172,839 円
ここでは、{値:>12,}のようにして右寄せ(>)と桁区切り(,)、幅指定(12)を組み合わせています。
ログ出力・エラーメッセージでの実例

ログやエラーメッセージには、f-stringが非常に相性が良いです。
変数名と値をわかりやすく並べることができます。
from datetime import datetime
def log_login(user_id: int, success: bool) -> None:
now = datetime.now()
level = "INFO" if success else "WARN"
status = "success" if success else "failed"
print(f"{now:%Y-%m-%d %H:%M:%S} [{level}] user_id={user_id} status={status}")
log_login(123, True)
log_login(456, False)
2024-05-01 14:30:45 [INFO] user_id=123 status=success
2024-05-01 14:30:45 [WARN] user_id=456 status=failed
また、例外処理でのエラーメッセージにも活用できます。
def divide(a: float, b: float) -> float:
if b == 0:
# f-stringで詳細なエラーメッセージを作る
raise ValueError(f"0では割り算できません: a={a}, b={b}")
return a / b
try:
divide(10, 0)
except ValueError as e:
print(f"エラーが発生しました: {e}")
エラーが発生しました: 0では割り算できません: a=10, b=0
ログやエラーの情報量を増やしても、f-stringならコードの見通しを保ちやすくなります。
テーブル形式の整形出力サンプル

f-stringを使うと、コンソールに表示する簡易テーブルをきれいに整形できます。
items = [
("Apple", 3, 120),
("Banana", 5, 80),
("Orange", 2, 150),
]
# ヘッダ行
print(f"{'商品名':<10} {'数量':>4} {'単価':>6} {'小計':>8}")
# 区切り線
print("-" * 32)
# 各行
for name, qty, unit_price in items:
subtotal = qty * unit_price
print(
f"{name:<10} " # 左寄せ、幅10
f"{qty:>4} " # 右寄せ、幅4
f"{unit_price:>6} " # 右寄せ、幅6
f"{subtotal:>8}" # 右寄せ、幅8
)
商品名 数量 単価 小計
--------------------------------
Apple 3 120 360
Banana 5 80 400
Orange 2 150 300
列ごとに幅と寄せ方向を指定するだけで、見やすいテーブルを簡単に作成できます。
レポート出力や簡易ツールで非常に有用です。
JSON風・辞書オブジェクトの整形出力

辞書オブジェクトをデバッグ目的で見やすく表示したい場合、f-stringとjson.dumpsを組み合わせるのが便利です。
import json
user = {
"id": 123,
"name": "Alice",
"active": True,
"roles": ["admin", "editor"],
}
# JSON風に整形して出力
json_text = json.dumps(user, ensure_ascii=False, indent=2)
print(f"ユーザーデータ:\n{json_text}")
ユーザーデータ:
{
"id": 123,
"name": "Alice",
"active": true,
"roles": [
"admin",
"editor"
]
}
f-stringに直接辞書を埋め込むと{'id': 123, ...}のようなPython表記になりますが、JSON風にしたい場合はjson.dumpsを通してから埋め込むときれいです。
実務で使えるf-stringスニペット集

最後に、実務でそのまま使える小さなスニペットをいくつか紹介します。
1. 行番号付きログ
def log_with_line(message: str, line_no: int) -> None:
print(f"[line {line_no:04}] {message}")
log_with_line("処理を開始します", 1)
log_with_line("データを読み込みました", 15)
[line 0001] 処理を開始します
[line 0015] データを読み込みました
2. ファイルパスの生成
project = "report"
date = "2024-05-01"
version = 2
filename = f"{project}_{date}_v{version:02}.csv"
print(filename)
report_2024-05-01_v02.csv
3. 進捗表示(簡易プログレス)
total = 100
for i in range(0, total + 1, 20):
percent = i / total
bar = "#" * (i // 10)
print(f"{i:3}/{total} ({percent:>5.1%}) [{bar:<10}]")
0/100 ( 0.0%) [ ]
20/100 ( 20.0%) [## ]
40/100 ( 40.0%) [#### ]
60/100 ( 60.0%) [###### ]
80/100 ( 80.0%) [######## ]
100/100 (100.0%) [##########]
4. SQLログの整形表示(あくまで表示用)
table = "users"
user_id = 123
status = "active"
sql = (
f"SELECT *\n"
f"FROM {table}\n"
f"WHERE id = {user_id} AND status = '{status}';"
)
print(sql)
SELECT *
FROM users
WHERE id = 123 AND status = 'active';
※実際のSQL実行にはプレースホルダを使い、f-stringで直接組み立てて実行しないようにしてください(セキュリティ上の理由)。
まとめ
f-stringは、Python 3.6以降で利用できる強力かつ読みやすい文字列フォーマット機能です。
変数や式を{}の中に書くだけで簡潔に表現でき、数値・日付フォーマット、ログ出力、テーブル表示など幅広い用途に活用できます。
一方で、波かっこのエスケープやクォートの扱い、全角文字の幅、セキュリティ意識など、押さえておくべき注意点もあります。
この記事のサンプルやスニペットを参考に、自分のプロジェクトでも積極的にf-stringを使いこなし、コードの可読性と生産性を高めていってください。
