Pythonの文字列フォーマットまとめ(%記法、format文、f文字列)

Python

この記事では、Pythonの文字列フォーマットについて説明します。実装中に困ったらいつでも参照できる備忘録としてご活用ください。

基本的な文字列フォーマット

Pythonで文字列をフォーマットする方法は主に3つあります。

  • %記法
  • format文
  • f文字列

それぞれの基本的な使い方を見ていきましょう。

%記法は最も古い方法ですが、依然として使用されています。

プレースホルダーに%+(型を表す1文字)を使用し、後に%を続けてフォーマットする変数を記述します。

シンプルで直感的ですが、複雑なフォーマットでは読みにくくなる場合があります。

name = "Alice"
age = 30
print("My name is %s and I'm %d years old" % (name, age))
# 出力: My name is Alice and I'm 30 years old

format文は、より柔軟で読みやすい方法です。

プレースホルダーに{}を使用し、後に.fortmat()を続けてフォーマットする変数を記述します。

順序を変更したり、同じ値を複数回使用する時に便利です。

name = "Bob"
age = 25
print("My name is {} and I'm {} years old".format(name, age))
# 出力: My name is Bob and I'm 25 years old

# インデックスを使用することもできます
print("My name is {0} and I'm {1} years old".format(name, age))
# 出力: My name is Bob and I'm 25 years old

f文字列(フォーマット済み文字列リテラル)は、Python 3.6以降で導入された最も新しい方法です。

頭にfをつけ、プレースホルダーの{}の中に変数を直接記述します。

変数名を使える分、可読性が高いです。式を直接埋め込むこともできます。

name = "Charlie"
age = 35
print(f"My name is {name} and I'm {age} years old")
# 出力: My name is Charlie and I'm 35 years old

注意点:

  • プレースホルダーには、後述のようにデータ型や形式を表す文字(s,d,fなど)を明示することができますが、format文やf文字列では型指定文字の省略が可能です。
  • %記法では型指定文字の省略はできません。

数値のフォーマット

整数、浮動小数点数、そして様々な基数(2進数、8進数、16進数)でのフォーマットが可能です。

整数・浮動小数点数

整数はd、浮動小数点数はfで表します。

  • %記法:
number = 42
pi = 3.14159265
print("%d" % number)  # 出力: 42
print("%f" % pi)  # 出力: 3.141593

  • format文:
number = 42
pi = 3.14159265
print("{:d}".format(number))  # 出力: 42
print("{:f}".format(pi))  # 出力: 3.141593

  • f文字列:
number = 42
pi = 3.14159265
print(f"{number:d}")  # 出力: 42
print(f"{pi:f}")  # 出力: 3.141593

2進数、8進数、16進数表示

  • %記法:

注:%記法では2進数表記(%b)には対応していない。

number = 42
print("%o" % number)  # 出力: 52 (8進数)
print("%x" % number)  # 出力: 2a (16進数、小文字)
print("%X" % number)  # 出力: 2A (16進数、大文字)

  • format文:
number = 42
print("{:b}".format(number))  # 出力: 101010
print("{:o}".format(number))  # 出力: 52
print("{:x}".format(number))  # 出力: 2a
print("{:X}".format(number))  # 出力: 2A

  • f文字列:
number = 42
print(f"{number:b}")  # 出力: 101010
print(f"{number:o}")  # 出力: 52
print(f"{number:x}")  # 出力: 2a
print(f"{number:X}")  # 出力: 2A

指数表示

小文字のe、大文字のEでそれぞれ指数表示にできます。

  • %記法:
pi = 3.14159265
print("%e" % pi)  # 出力: 3.141593e+00
print("%E" % pi)  # 出力: 3.141593E+00

  • format文:
pi = 3.14159265
print("{:e}".format(pi))  # 出力: 3.141593e+00
print("{:E}".format(pi))  # 出力: 3.141593E+00

  • f文字列:
pi = 3.14159265
print(f"{pi:e}")  # 出力: 3.141593e+00
print(f"{pi:E}")  # 出力: 3.141593E+00

パーセンテージ表示

  • %記法:

注:%記法ではパーセンテージ表示は対応していないので、数値を100倍する必要がある。%% は、パーセンテージ記号 (%) をそのまま出力するという意味。もしくは、%の後にformatを続けることで、あらかじめフォーマットした後に文字列として%sに格納する方法もある。

percentage = 0.7854
print("%f%%" % (percentage * 100))  # 出力: 78.540000%
print("%s" % format(percentage,"%"))  # 出力: 78.540000%

  • format文:
percentage = 0.7854
print("{:%}".format(percentage))  # 出力: 78.540000%

  • f文字列:
percentage = 0.7854
print(f"{percentage:%}")  # 出力: 78.540000%

型の互換性と自動キャスト

指定されたフォーマットと実際の値の型が異なる場合、自動的にキャストが試みられます。いくつかの挙動には注意が必要です。

  • 整数を浮動小数点数のフォーマットで表示:
number = 42
print("%f" % number)  # 出力: 42.000000
print("{:f}".format(number))  # 出力: 42.000000
print(f"{number:f}")  # 出力: 42.000000

  • 浮動小数点数を整数のフォーマットで表示(小数部分切り捨て):
number = 42.75
print("%d" % number)  # 出力: 42 (警告が出る場合があります)
print("{:d}".format(int(number)))  # 出力: 42 (明示的なキャストが必要)
print(f"{int(number):d}")  # 出力: 42 (明示的なキャストが必要)

  • 文字列を数値のフォーマットで表示:
text = "42"
print("%d" % int(text))  # 出力: 42 (明示的なキャストが必要)
print("{:d}".format(int(text)))  # 出力: 42 (明示的なキャストが必要)
print(f"{int(text):d}")  # 出力: 42 (明示的なキャストが必要)

注意点:

  • 整数から浮動小数点数へのキャストは精度が変わる可能性があります。
  • 浮動小数点数から整数へのキャストは、小数部分が切り捨てられます。警告を避けるため、明示的なキャスト(int()関数の使用)が推奨されます。
  • 文字列を数値として扱う場合は、必ずキャストが必要です。そうしないと TypeError が発生します。
  • 複雑なフォーマット指定子(例:%g)を使用する場合、予期せぬ結果を避けるため、値の型をよく確認してください。

特殊な数値表現

プラス/マイナス表記にしたり、3桁ごとにカンマ区切りすることもできます。

符号表示(正負の記号)

  • %記法:
positive = 42
negative = -42
print("%+d" % positive)  # 出力: +42
print("%+d" % negative)  # 出力: -42

  • format文:
positive = 42
negative = -42
print("{:+d}".format(positive))  # 出力: +42
print("{:+d}".format(negative))  # 出力: -42

  • f文字列:
positive = 42
negative = -42
print(f"{positive:+d}")  # 出力: +42
print(f"{negative:+d}")  # 出力: -42

千の位区切り

  • %記法:

注:%記法はカンマ区切りに対応していないため、あらかじめformatした後で文字列として%sに代入する方法がある。

large_number = 1234567
print("%s" % format(large_number, ','))  # 出力: 1,234,567

  • format文:
large_number = 1234567
print("{:,}".format(large_number))  # 出力: 1,234,567

  • f文字列:
large_number = 1234567
print(f"{large_number:,}")  # 出力: 1,234,567

幅指定と文字列の配置

特定の幅で左寄せ、右寄せ、または中央揃えにしたり、特定の文字で余白を埋めることもできます。

幅指定と配置の基本形式

配置と幅指定の基本形式は以下の通りです。

:[埋め文字][配置][][.精度][]

  • 埋め文字: スペースの代わりに使用する文字(省略時はスペース)
  • 配置: <(左揃え)、^(中央揃え)、>(右揃え)
  • 幅: 全体の幅を指定する数値
  • 精度: 小数点以下の桁数(浮動小数点数の場合)または最大文字数(文字列の場合)
  • 型: s(文字列)、d(整数)、f(浮動小数点数)など

左寄せ/中央寄せ/右寄せ

幅指定の数値の左側に、文字列の配置方法を指定することができます。

  • %記法では通常右寄せで、「%-10s」のようにマイナスをつけると左寄せになります。
  • format文とf文字列では、<(左揃え)、^(中央揃え)、>(右揃え)で区別します。(何も指定しない場合は左寄せ)

注:指定した幅よりも文字数が多い場合は、文字全体が優先して表示されます。(最小表示幅を指定)

  • %記法:

注:%記法では中央揃えに直接対応していない。

print("%-10s" % "left")  # 出力: "left      "
print("%10s" % "right")  # 出力: "     right"

  • format文:
print("{:<10}".format("left"))  # 出力: "left      "
print("{:^10}".format("center"))  # 出力: "  center  "
print("{:>10}".format("right"))  # 出力: "     right"

  • f文字列:
print(f"{'left':<10}")  # 出力: "left      "
print(f"{'center':^10}")  # 出力: "  center  "
print(f"{'right':>10}")  # 出力: "     right"

動的な幅指定

幅を変数で指定することもできます。

  • %記法: (*で変数化)
width = 10
print("%*s" % (width, "dynamic"))  # 出力: "   dynamic"

  • format文:
width = 10
print("{:>{}}".format("dynamic", width))  # 出力: "   dynamic"

  • f文字列:
width = 10
print(f"{'dynamic':>{width}}")  # 出力: "   dynamic"

文字埋め(ゼロ埋め)

指定幅まで特定の文字で埋めることもできます(%記法はゼロ埋めのみ)。特にゼロ埋めは配置方法を指定しなくてもデフォルトで右寄せになります。

  • %記法:

注:%記法は特定の文字で埋める機能はないが、ゼロ埋めは対応している。

print("%010d" % 42)  # 出力: 0000000042
print("%010f" % 3.14159265)  # 出力: 003.141593

  • format文:
# 文字埋め
print("{:*>10}".format("python"))  # 出力: "****python"
print("{:#>10}".format(42))  # 出力: "########42"

# ゼロ埋め
print("{:010}".format(42))  # 出力: "0000000042"
print("{:010}".format(3.14))  # 出力: "0000003.14"
print("{:0>10}".format("python"))  # 出力: "0000python" (文字列に対してもゼロ埋めは可能だが、配置指定が必要)

  • f文字列:
# 文字埋め
print(f"{'python':*>10}")  # 出力: "****python"
print(f"{42:#>10}")  # 出力: "########42"

# ゼロ埋め
print(f"{42:010}")  # 出力: "0000000042"
print(f"{3.14:010}")  # 出力: "0000003.14"
print(f"{'python':0>10}")  # 出力: "0000python" (文字列に対してもゼロ埋めは可能だが、配置指定が必要)

精度指定(数値)

指定幅の後のドット付きの数字は、表示する値が数値か文字列かによって異なる振る舞いをします。

浮動小数点数の場合、小数点以下の桁数を指定します。

  • %記法:
pi = 3.14159265
print("%f" % pi)   # 出力: 3.141593
print("%.2f" % pi)   # 出力: 3.14
print("%.5f" % pi)   # 出力: 3.14159

  • format文:
pi = 3.14159265
print("{:f}".format(pi))   # 出力: 3.141593
print("{:.2f}".format(pi))   # 出力: 3.14
print("{:.5f}".format(pi))   # 出力: 3.14159

  • f文字列:
pi = 3.14159265
print(f"{pi:f}")   # 出力: 3.141593
print(f"{pi:.2f}")   # 出力: 3.14
print(f"{pi:.5f}")   # 出力: 3.14159

最大表示幅(文字列)

文字列の場合、ドットの後の数字はは最大表示幅として機能し、文字列を切り詰めます。

  • %記法:
text = "python"
print("%s" % text)   # 出力: python
print("%.3s" % text)   # 出力: pyt

  • format文:
text = "python"
print("{:s}".format(text))   # 出力: python
print("{:.3s}".format(text))   # 出力: pyt

  • f文字列:
text = "python"
print(f"{text:s}")   # 出力: python
print(f"{text:.3s}")   # 出力: pyt

注意点

  • 整数に対する精度指定(例: .3dなど)はエラーになります。ただし、%記法ではドットが無視され、最小表示幅が3として動きます。
  • 文字列の最小表示幅(ドット前)と最大表示幅(ドット後)を組み合わせる場合、最大表示幅(ドットの後)が優先されます。下の例では最大幅3(.3s)が適用された後、10文字分の幅が確保されています
text = "python"
print(f"{text:10.3s}")  # 出力: "pyt       "

複合データ型とフォーマット

リストや辞書などの複合データ型と組み合わせることも可能です。

リストの使用

  • %記法:

注:%記法ではリストは使用できない。タプルに変換する必要がある。

fruits = ['apple', 'banana', 'cherry']
print("I like %s, %s, and %s" % tuple(fruits))
# 出力: I like apple, banana, and cherry

  • format文:
fruits = ['apple', 'banana', 'cherry']

# 0にリストそのものが入るので、そこから呼び出し可能
print("I like {0[0]}, {0[1]}, and {0[2]}".format(fruits))
# 出力: I like apple, banana, and cherry

# 可変長引数として、unpackしてformatに渡しても良い
print("I like {0}, {1}, and {2}".format(*fruits))
# 出力: I like apple, banana, and cherry

  • f文字列:
fruits = ['apple', 'banana', 'cherry']
print(f"I like {fruits[0]}, {fruits[1]}, and {fruits[2]}")
# 出力: I like apple, banana, and cherry

辞書の使用

辞書を使用すると、キーワード引数のように値を参照できます。

  • %記法:
person = {'name': 'Alice', 'age': 30}
print("%(name)s is %(age)d years old" % person)
# 出力: Alice is 30 years old

  • format文:
person = {'name': 'Alice', 'age': 30}

# 0に辞書そのものが入るので、そこから呼び出し可能
print("{0[name]} is {0日付未入力} years old".format(person))
# 出力: Alice is 30 years old

# 可変長引数として、unpackしてformatに渡しても良い
print("{name} is {age} years old".format(**person))
# 出力: Alice is 30 years old

  • f文字列:
person = {'name': 'Alice', 'age': 30}

print(f"{person['name']} is {person['age']} years old")
# 出力: Alice is 30 years old

複雑なデータ構造の扱い

ネストされた辞書やリストなど、より複雑なデータ構造も扱えます。

data = {
    'users': [
        {'name': 'Alice', 'age': 30},
        {'name': 'Bob', 'age': 25}
    ]
}

for user in data['users']:
    print(f"{user['name']} is {user['age']} years old")

# 出力:
# Alice is 30 years old
# Bob is 25 years old

応用例

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

datetimeモジュールを使用して、日付と時刻を柔軟にフォーマットできます。

from datetime import datetime

sample_datetime = datetime(year=2024, month=6, day=30, hour=12, minute=30, second=15)
print(f"{sample_datetime:%Y-%m-%d %H:%M:%S}")   # 出力: 2024-06-30 12:30:15

テーブル形式の出力

簡易的なテーブル形式を出力する実装例です。

data = [
    ('Alice', 30, 'New York'),
    ('Bob', 25, 'Los Angeles'),
    ('Charlie', 35, 'Chicago')
]

print(f"{'Name':^10}|{'Age':^5}|{'City':^15}")
print("-" * 10 + "+" + "-" * 5 + "+" + "-" * 15)
for name, age, city in data:
    print(f"{name:<10}|{age:>5}|{city:<15}")
  
# 出力:
#    Name   | Age |     City      
# ----------+-----+---------------
# Alice     |   30|New York       
# Bob       |   25|Los Angeles    
# Charlie   |   35|Chicago            

デバッグ時の活用法

f文字列を使用すると、変数名と値を同時に表示でき、デバッグに便利です。

x = 10
y = 20
print(f"{x=}, {y=}")  # 出力: x=10, y=20

パフォーマンス

一般的に、f文字列が最も高速です。ただし、頻繁に実行される部分では、事前に文字列をコンパイルすることで、さらにパフォーマンスを向上させることができます。

from string import Template

t = Template('Hello, $name!')
name = "Alice"
print(t.substitute(name=name))

この例では、substitute()メソッドを使用して、テンプレート文字列中のプレースホルダ $nameを変数nameの値に置換しています。

まとめ

pythonのフォーマットの仕方についてまとめました。いずれの記法もかなり柔軟にフォーマットを設定できるので、活用しやすいと思います。ぜひ参考にしてみてください。

さらに学びたい方へ

Udemyの以下の動画が参考になりますので、ぜひこちらもご覧ください。

(Udemy動画は結構高いものもありますが、セールで80%OFFになったりもするので、セールのタイミングで一気に購入してしまうのがおすすめです)

コメント

タイトルとURLをコピーしました