Python 書式指定一覧

# 概要

いい感じのPython文字列フォーマット一覧がどれだけ探しても見つからないので自分でまとめました。
サンプルは原則としてf-stringを利用していますので、Python3.6以降を使用している方は読みやすいかもしれません。
サンプルの動作確認はすべて Python3.8.6 において行っています。
一部これ以降のバージョンに関する記述がありますが、それらはすべて公式のドキュメントに拠ったものです。

Pythonの書式指定についてもっと詳しく知りたい方は [こちら](https://docs.python.org/ja/3/library/string.html#format-specification-mini-language, "書式指定ミニ言語仕様 - PythonDocs(JP)") のドキュメントをご覧ください。


# 書式指定のキホン

## 書式指定を行うメソッド

書式指定を利用するには `format()` 、 `str.format()` 、 `f-string` 、 `% 書式` のいずれかを使います。図でサクッと4つを比較してみましょう。

![string_formatting_method_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739387/e2b22358-cf58-0460-195a-514777b4aafa.jpeg)
![string_formatting_method_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739387/ae2a229f-3b5c-dc54-eb3d-8dfbc192ac6f.jpeg)
![string_formatting_method_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739387/05aa707d-1488-c01d-001e-b709be425355.jpeg)
![string_formatting_method_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739387/475c7d94-456f-1a42-e468-a58e5525e769.jpeg)

***

<details>
<summary>メソッドの使い方（ざっくりと文字説明）</summary>

`format()` は次のように第1引数に **値** 、第2引数に **書式を指定する特別な文字列**（後述） を設定します。

```py:format()
format(値, 書式指定) # -> str
```

`str.format()` は文字列中の `{}` を **置換フィールド**（プレースホルダー）とみなし、引数に設定した値をフォーマットして埋め込みます。書式指定は `{}` 内に `:` を伴って行います。値は文字列リテラルの `{}` 内でなくメソッドの引数に与えます。

```py:str.format()
"{:書式指定}".format(値) # -> str
```

`f-string` （フォーマット済み文字列リテラル）は、従来の文字列リテラル `""` に `str.format()` の考え方を組み込んだ、より簡潔な記述を可能にした文字列リテラルです。Python3.6で登場しました。

```py:f-string
f"{値:書式指定}" # -> str
```

ほかにも C でいうところの `printf()` のように使用できる `% 書式` を用いた記法も用意されています。

こちらの説明に関しましては、可読性の面から「できるだけ `f-string` か `str.format()` を使ってほしい！」という思いを込めまして割愛いたします。ちなみに [こちら](https://qiita.com/phyblas/items/0a122fe4a18a18a83050 "Qiitaの記事: pythonのf-stringとformatとパーセント%の書式の速度の比較 - @phyblas さん") の記事によりますと速度は一般にもっとも速いようです。

> 2020-03-13 : `str.format()` と `% 書式` の不足についてコメントでご指摘いただきましたので追記いたしました。

</details>


## 書式指定の文法

「書式指定の方法と種類だけ知りたい！」という方はこの節は飛ばしていただいて構いません。
ですが「Pythonの書式指定をマスターしたい！」という方にはぜひご一読いただきたい内容になっています。
f-stringが説明の中心になります。

***

ドキュメントでは書式指定の文法構造について次のように表現されています。

![f_string_format_syntax_form.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739387/98c4629c-1618-b12c-0601-ed41d749acdb.jpeg)

図からも分かるように、書式指定は「フィールド」と呼ばれる `field_name` `conversion` `format_spec` の3要素で構成されています。それぞれの持つ役割は次の通りです。
- `field_name` (**必須**)
書式指定を行う対象オブジェクトを指定します。
必ず置換フィールドの先頭に配置します。

- `conversion` (**任意**)
`field_name` に与えられたオブジェクトを文字列として埋め込む上で、最初に行う基礎的な変換を指定します。`!` を先頭に伴います。
オブジェクト指向を採用しているPythonにおいて、オブジェクトの文字列化に期待されるものがただ一つであるとは限りません。この問題を解決するためにPythonではクラスに特殊メソッドの定義を可能にすることで対応できるようにしています。
このフィールドに指定することによって機能するのは上に記した通り一部の特殊メソッドであり、このフィールドに指定できる文字は Python3.10 現在で `s` `r` `a` の3つです。これらは以下に示す特殊メソッドに紐づいています。処理によって返された `str` が後の `format_spec` での処理に与えられます。

| オプション | 対応するメソッド | 等価のメソッド |
|:-:|:-:|:-:|
| `s` | `__str__()` | `str()` |
| `r` | `__repr__()` | `repr()` |
| `a` | `__ascii__()` | `ascii()` |

なお、`conversion` を指定した場合の返り値は必ず `str` となりますから、`format_spec` フィールドに指定可能な指定子のうち多くが適用不可になる点について注意が必要です。

```py:等価である変換指定
print(f"{str(obj)}")
print(f"{obj!s}")
print(f"{obj}") # f-string はデフォルトで !s を選択します

print(f"{repr(obj)}")
print(f"{obj!r}")

print(f"{ascii(obj)}")
print(f"{obj!a}")
```

- `format_spec` (**任意**)
「 `field_name` フィールドに指定したオブジェクトそのもの」か、「 `conversion` フィールドの指定によって変換された文字列」の書式指定を行います。`:` を先頭に伴います。これを用いた書式指定に関してはそれぞれについて後に詳しく説明しています。


# 配置

## 自動設定(width)

指定した幅の中でそれぞれの型ごとに自動で最適な配置を行います。
```py
print(f"'{123:10}'")    # int
print(f"'{123.45:10}'") # float
print(f"'{'hoge':10}'") # str
print(f"'{True:10}'")   # bool
print(f"'{False:10}'")  # bool
```

```py:実行結果
'       123' # int
'    123.45' # float
'hoge      ' # str
'         1' # bool(True)
'         0' # bool(False)
```

なお、`None` が与えられた場合は TypeError が発生します。

```py:Noneを与える
print(f"'{None:10}'")   # None
# TypeError: unsupported format string passed to NoneType.__format__
```

## 任意設定(align)

記号（<, ^, &gt;）で配置を指定して直後に確保する字数を指定します。

```py:
a = "hoge"
print(f"'{a:<10}'") # 左寄せ
print(f"'{a:^10}'") # 中央寄せ
print(f"'{a:>10}'") # 右寄せ
```

```py:実行結果
'hoge      ' # 左寄せ
'   hoge   ' # 中央寄せ
'      hoge' # 右寄せ
```

なお、中央揃えにおいて左右の余白が一致しない場合は左に寄せられます。

```py
a = "hoge"  # 偶数文字
b = "abcde" # 奇数文字

print(f"a = '{a:^10}'") # 偶数余白に対して偶数文字
print(f"b = '{b:^10}'") # 偶数余白に対して奇数文字

```

```py:実行結果
'   hoge   ' # 中央
'  abcde   ' # 中央より少し左
```

## 余白を文字埋め(fill)

余白をスペース以外で表す（文字埋めする）場合、次のように1文字を指定し文字埋めすることが可能です。
0埋めを行いたい場合は特別なオプションが用意されていますので、これの詳細については後述します。

```py
print(f"'{a:.<20}'") # 左寄せ（ドット埋め）
print(f"'{a:.^20}'") # 中央寄せ（ドット埋め）
print(f"'{a:.>20}'") # 右寄せ（ドット埋め）
# 'hoge................'
# '........hoge........'
# '................hoge'
```


# 数値の書式

## 桁数指定(.precision)

小数の精度を指定できます。

```py
c = 1234.5678
print(f"c = {c:.2f}") # 小数第2位まで（小数第3位を四捨五入）
print(f"c = {c:10.2f}") # 10文字確保して小数第2位まで
# c = 1234.57
# c =    1234.57
```

なお、小数点以下の余白については自動的に0埋めされます。
一部のPython情報サイトで「 小数点以下の0埋めは `.` の直後に `0` を付して指定する」旨の記述がみられましたが、比較してみると等価であるようです。

```py
print(f"c = {c:.8f}") # 小数点以下に確保した文字幅が小数点以下の桁数を上回った場合
print(f"c = {c:.08f}") # 一部のサイトで解説されていた小数点以下0埋めの指定方法

# c = 1234.56780000
# c = 1234.56780000
```

## 3桁区切り(grouping_option)

```py
d = 123456789
print(f"d = {d:,}") # カンマ
print(f"d = {d:_}") # アンダースコア
# d = 123,456,789
# d = 123_456_789
```

## 正負符号(sign)
```py
e = 123
f = -456

print(f"e = {e:+}") # 正負の値それぞれでプラスかマイナスを付す。
print(f"f = {f:+}")

print(f"e = {e:-}") # 負の値のみマイナスを付す。（デフォルトの挙動）
print(f"f = {f:-}")

print(f"e = {e: }") # 正の値のとき1マスを余分に確保して桁を揃える。
print(f"f = {f: }")

# e = +123
# f = -456
# e = 123
# f = -456
# e =  123
# f = -456
```

## 符号と値の間の文字埋め(fill, align)

`=` を使用することで符号と値の間に空白がある場合に限り文字埋めが可能です。（数値型のみ有効）

```py
print(f"'{-123:p=10}'") # 文字埋め(int)
'-pppppp123'
```

なお、ゼロ埋めに関しては後述する `0` オプションが用意されていますから、以下2つは等価となります。

```py
print(f"'{123:0=+10}'") # ゼロ埋め(fillオプション)
print(f"'{123:+010}'")  # ゼロ埋め(0オプション)
# '+000000123'
# '+000000123'
```

## 表示型(type)

次に示す文字を指定することで数値を特別な表示に変換して出力します。


### 整数の表示型

intに限り次が利用できます。floatでは利用できません。

| 文字 | 説明 |
|:-:|:-|
| b | 2進数 |
| o | 8進数 |
| d | 10進数 |
| x | 16進数（英字は小文字） |
| X | 16進数（英字は大文字） |
| c | 数値に対応するUnicode文字 |
| n | `d` にロケール依存のセパレータを挿入する |
| (None) | `d` に同じ |

※ `n` 設定時の挙動は確認できませんでした。

```py
g = 1500
print(f"g = {g:b}")   # g = 10111011100
print(f"g = {g:o}")   # g = 2734
print(f"g = {g:d}")   # g = 1500
print(f"g = {g:x}")   # g = 5dc
print(f"g = {g:X}")   # g = 5DC
print(f"g = {g:c}")   # g = ל
print(f"g = {g:n}")   # g = 1500
print(f"g = {g:,d}")  # g = 1,500
print(f"g = {g:}")    # g = 1500
```

***

### 整数と小数の表現型

intとfloatの両方で利用できます。

| 文字 | 説明 |
|:-:|:-|
| e | eを用いた指数表示します。 |
| E | `e` の代わりに `E` を使用する点を除いて `e` と同じです。 |
| f | 固定小数点表記を行います。小数点以下桁数絶対主義といったところです。 |
| F | `nan` の代わりに `NAN` 、 `inf` の代わりに `INF` を使用する点を除いて `f` と同じです。 |
| g | 与えられた小数の小数点以下桁数に応じて `e` と `f` を使い分けます。 |
| G | `E` と `F` に示した通り、特殊な文字が大文字であらわされます。 |
| n | 略 |
| % | 固定小数点表記（`f`）を利用した数値を100倍して末尾に % を付すことでパーセント表示します。 |
| (None) | 主に `g` をとります。 |

```py
h = 0.9345
print(f"h = {h:e}")  # h = 9.345000e-01
print(f"h = {h:E}")  # h = 9.345000E-01
print(f"h = {h:f}")  # h = 0.934500
print(f"h = {h:F}")  # h = 0.934500
# g, G については後節参照
print(f"h = {h:n}")  # h = 0.9345
print(f"h = {h:%}")  # h = 93.450000%
print(f"h = {h:}")   # h = 0.9345
```

#### `g` および `G` の内部的な条件

`g` は与えられた数値を自動で判定して `e`（指数表記） か `f`（固定小数点表記）を判定します。
具体的な分岐の基準は有効数字6桁であり、そのときに整数部の桁数が1を超えている際は `e` の指数表記が適用され、そうでなければ `f` の固定小数点表記が適用されます。

<details>
<summary>試したコードとその結果</summary>

ドキュメントに説明が用意されていますがすこし難しいので実践を通して条件を確認してみました。

##### 小数部の桁数を増やす

```py:
print(f"{1.2345:g}")       # 有効数字5桁
print(f"{1.23456:g}")      # 有効数字6桁
print(f"{1.234567:g}")     # 有効数字7桁
print(f"{0.1234567:g}")    # 有効数字7桁
# 1.2345
# 1.23456
# 1.23457
# 0.123457
```

##### 整数部の桁数を増やす

```py:
print(f"{12345:g}")        # 有効数字5桁
print(f"{123456:g}")       # 有効数字6桁
print(f"{1234567:g}")      # 有効数字7桁
print(f"{1234567.89:g}")   # 有効数字7桁
# 12345
# 123456
# 1.23457e+06
# 1.23457e+06
```

</details>



# 書式指定子の順番

書式指定子の順番について、公式ドキュメントでは次のように説明されています。

```
[[fill]align][sign][#][0][width][grouping_option][.precision][type]
```

見慣れない `#` と `0` が登場してきましたので説明します。
- `#` は **表示型(type)** での、2進数や8進数、16進数といった値に 接頭語 (prefix) として 0b, 0o, 0xを付けたり、有効数字表記 `g` において小数点以下を0埋めしたりする特殊オプションです。
- `0` は0専用の文字埋めオプションです。本来、文字埋めを行う際は **fill** にあたる先頭に文字を指定しますが、0のみは特別に **幅指定(width)** の直前に設定することができます。

```py:オプション '0' の使用例
i = 1.56789
print(f"i = {i:010}")    # 0埋めかつ、widthに10を指定した状態
print(f"i = {i:010.2f}") # 0埋めかつ、widthに10、.precisionに2、typeにfを指定した状態
 # i = 0001.56789
 # i = 0000001.57
```

なお、Python3.10 からはwidthに何も設定せずに `0` オプションを設定する、以下のような記述が可能になりました。

```py:
print(f"i = {i:0.2f}") # Python3.10から有効
```

以上2点を踏まえて、もりもりセットを組んでみたサンプルがこちらです。

```py
print(f"{123.45678:>+010.4%}")
print(f"{123.45678:<010.1e}")
print(f"{123:^ #10b}")
print(f"{9999:a>#10X}")
# +12345.6780%
# 1.2e+02000
#  0b1111011
# aaaa0X270F
```

![f_string_format_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739387/9f832b89-8ca3-fbca-8d1c-cc52dcc9ad70.jpeg)
![f_string_format_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739387/15bef9c1-fa0b-2fed-77c7-c65cca7c66b9.jpeg)
![f_string_format_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739387/ae1d253b-8c3d-c381-87bb-b2eb2d9109f8.jpeg)
![f_string_format_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/739387/bb068ed7-6bd6-067d-588d-421c94165a6e.jpeg)



# 後記
つたない文章ではございましたが、お読みいただきありがとうございました！
皆さんのより良いPythonライフの一助になりましたら幸いです！