Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

Python

Pythonのstr.formatと置換フィールドと{0:{width}{base}}などの書式指定ミニ言語仕様の基本的な解説

Pythonのstr.format()で使える書式指定ミニ言語仕様の基本の解説

前回の記事「【Python入門】文字列操作のstr.format()と書式指定文字列の基本的使い方の解説」で、基本的なstr.formatの使い方を解説しましたが、今回はその応用編みたいなもので、str.formatを書式指定ミニ言語仕様と組み合わせて使ってみようという記事です。

まずは{}で囲まれた置換フィールドの使い方の基本から見ていきます。

置換フィールドとその書き方

置換フィールドとは?

まずstr.format()の使い方の復習ですが、

print("テスト本番まであと{remaining_days}日です".format(remaining_days = 7))
print("テスト本番まであと{}日です".format(7))

# 上の実行結果→ テスト本番まであと7日です 

このように使い、文字列の中に{}を使って情報を埋め込むことができるという機能でした。

この、{}に囲まれた部分を置換フィールド(replacement field)といいます。

置換フィールドの文法と使用例

置換フィールドの文法

置換フィールドは次のように3つのパートから構成されます。

{①②③}

この3つのパートについてはそれぞれ次のような文法となります。

パートフィールド名設定される情報
①(省略可能)field_name・指定なし
・数字
・キーワード
②(省略可能)! + conversion・!s
・!r
・!a
③(省略可能)format_spec書式指定ミニ言語仕様

今回のこの記事の中心は③についてです。しかし上述のように①、②について先に以下で見ていくことにします。そのほうが理解が深まりやすいと思います。では具体例を見てみましょう。

置換フィールドの使用例

公式ドキュメントの項目「書式指定例」を見てもらうと多くの使用例が紹介されていてとても勉強になります。今回の記事では以下、簡単で基本的な使い方だけ例として挙げておきます。

field_nameパートについて

# 01:位置引数のインデックス番号を使ったもの
'{0}, {1}, {2}'.format('a', 'b', 'c')

# 02: 何も設定しないと自動的に順番に代入される
'{}, {}, {}'.format('a', 'b', 'c')

# 03: 文字列のアンパックを使用
'{2}, {1}, {0}'.format(*'abc') 

# 04:引数が辞書の場合のアンパック
features = {'name': 'Tom', 'tall': '180'}
'Person: {name}, {tall}'.format(**features)

これらを実行すると上から順番に、

'a, b, c' 
'a, b, c'
'c, b, a'
'Person: Tom, 180'

となります。

! + conversionパートについて

! + conversionパートで使われる書式は、

パートフィールド名設定される情報
①(省略可能)field name・指定なし
・数字
・キーワード
②(省略可能)! + conversion・!s
・!r
・!a
③(省略可能)format spec書式指定ミニ言語仕様

!s、!r、!aの3種類です。

これらはそれぞれ順番に、

  • 組み込み関数str()を呼び出す
  • 組み込み関数repr()を呼び出す
  • 組み込み関数ascii()を呼び出す

という動きをします。

# 01: 組み込み関数str()を呼び出す
"彼は{0!s}です".format("田中") 

# 02: 組み込み関数repr()を呼び出す
"彼は{name!r}です".format(name="田中")

# 03: 組み込み関数ascii()を呼び出す
"彼は{!a}です".format("田中")

これらの実行結果は上から順番に、

'彼は田中です'
"彼は'田中'です"
"彼は'\\u7530\\u4e2d'です"

それぞれ実行結果がすべて異なっていますね。ascii()は、非ASCII 文字である日本語の全角文字・半角文字を、 \x 、 \u 、 \U エスケープを使ってエスケープして表示するという働きをするので上のような実行結果になっています。

format_specパートについて

この項目については改めて次の項目「書式指定ミニ言語仕様について」で独立して解説します。

書式指定ミニ言語仕様について

書式の新旧

公式ドキュメントの項目「書式指定ミニ言語仕様」

まず新旧の書式に違いがあります。

新旧書き方の例
‘%03.2f’
‘{03.2f}’

このように新しい書式では、

  • {}を使う
  • %の代わりに、:を使う

これら2点で違いがあります。今では特別な理由がなければ新しい方の書き方を使うようにしておけばいいでしょう。その使い方を見てみましょう。

書式の仕様

公式ドキュメントの項目「書式指定ミニ言語仕様」では、次のように書式の仕様が説明されています。

format_spec     ::=  [[fill]align][sign]["z"]["#"]["0"][width][grouping_option]["." precision][type]

以下の解説では、これらのうち[[fill]align]、[sing]、[width]、そして[type]の4つのパートついて簡単にみていきます。

基本的な使用例

[fill]align]:字詰めなどを設定する項目

#01 字詰め設定
"{2:}".format("Google", "Apple", "Microsoft", 200)
"{2:>20}".format("Google", "Apple", "Microsoft", 200)
"{2:<20}".format("Google", "Apple", "Microsoft", 200)

#02 「=」を使うと、数値型の符号と数字との間を指定文字で埋めることが可能
"{3:>=20}".format("Google", "Apple", "Microsoft", -103)
"{3:a=20}".format("Google", "Apple", "Microsoft", -103)
"{3:a=20}".format("Google", "Apple", "Microsoft", +103)
"{3:a=20}".format("Google", "Apple", "Microsoft", 103)

これらの実行結果は上から順番に、

'Microsoft'
'           Microsoft'
'Microsoft           '
'->>>>>>>>>>>>>>>>103'
'-aaaaaaaaaaaaaaaa103'
'aaaaaaaaaaaaaaaaa103'
'aaaaaaaaaaaaaaaaa103'

字詰めの設定で「>」または「<」を使った場合は右端・左端に11文字分のスペースができていますね。

そして「=」を使った場合は、その=の前に指定した文字によって、(今回は「=20」というように「20」を指定しているので)「全部で20文字となるよう」符号と数字との間が埋められています。各文字・記号とあわせて文字数を数えて見てください。

[sign]:符号の表示の設定

#01 +は、正の数、負の数の両方に符号をつける
"{3:}".format("Google", "Apple", "Microsoft", 103)
"{3:}".format("Google", "Apple", "Microsoft", -103)
"{3:+}".format("Google", "Apple", "Microsoft", 103)

実行結果は上から順番に、

'103'
'-103'
'+103'

「+」を指定した場合は、引数が正の数だろうと負の数だろうとそれに適した符号が自動的に付与されます。今回は103という正の数なので自動的に+がつけられていますね。

なお、コード3行目とそれに対応する結果2とを見ていただくとわかるでしょうが、何も指定しない場合は引数が負の数の場合にだけ自動的に-の符号がつけられます。

[width]:文字幅の設定


#06 字幅として9文字分を指定
"{3:9}".format("Google", "Apple", "Microsoft", +103)

#06-1 alignの「^」とともに使うと中央寄せ
"{3:^9}".format("Google", "Apple", "Microsoft", +103)

実行結果は上から順番に、

'      103'
'   103   '

「^」を使うと、特に字幅が設定されている場合に中央寄せでの表示が可能となります。今回は数字103という3文字に対して字幅を9で設定していますので中央寄せが可能の場合になります。

[type]:データの表示形式を設定(整数ならば◯進数表示が可能)

# Xを使って16進数表示
"{3:^9X}".format("Google", "Apple", "Microsoft", +103)

実行結果は、

'   67    '

となります。10進数で103という数字は16進数だと67になるわけですね。

このtypeについては、設定可能な表現形式を簡単にまとめると以下の通りです。

意味
‘s’通常の文字列。デフォルトでの設定。通常は省略される
None上’s’と同じ
'b'2進数
'c'文字。数値を対応する Unicode 文字に変換
'd'10進数
'o'8進数
'x'16進数 10進数で9を超える数字には小文字を使って表示
'X'16進数。10進数で9を超える数字には大文字を使って表示。'#' が指定された場合、接頭辞 '0x' も大文字 '0X' に。
'n'数値。区切り文字が挿入される
整数に対してNoneを使う場合'd' と同じ

応用的な使い方

さて上の基本が理解できればその応用編のような公式ドキュメントの「書式指定ミニ言語仕様¶」の項目に掲載されている次のコードが理解できると思います。

width = 5  # 字間の設定
for num in range(5,12): 
    # d: 10進数、X: 16進数、o: 8進数、b: 2進数
    for base in 'dXob':
        #{0:}の0はformat()の位置引数を参照(ここではnum)。0ではなくキーワードならキーワード引数を参照
        print('{0:{width}{base}}'.format(num, base=base, width=width), end=' ')
    print()

これを実行すると次のようになります。

    5     5     5   101
    6     6     6   110
    7     7     7   111
    8     8    10  1000
    9     9    11  1001
   10     A    12  1010
   11     B    13  1011

このコードを簡単に解説した次の概略図を見て下さい。

Python str.format

いかかでしょうか、最初はわかりにくいと思うかもしれませんが、上の基本的な使用例の内容と照らし合わせてゆっくりと考えてもらえればなるほどと納得していただけると思います。なお、Python学習におすすめの動画講座を以下の記事でまとめているので参考にしてみてください。

世界最大の動画学習サイトUdemyで、プログラミングを最速でマスターしましょう。

Udemy
愛を分かち合いましょう