Pythonができる文字列の事。中巻:format()の章

この記事の開発環境

  • バージョン: Python3.8
  • IDE: spacemacs
  • ライブラリ: cmath、datetime
  • 環境構築: pyenv、pyenv-virtualenv
  • OS: macOS & ubuntu 18.04

Pythonのフォーマットの概要

Pythonのテキスト処理サービスの1つであるフォーマット方法について取り上げていきたい。フォーマットは文字列型だけのものではなく、日付型や数値型も扱うことができ、型専用のフォーマット書式もある。また独自のフォーマット処理を作ることもできる。主にフォーマットの方法以下の3つがある。

  • 連結演算子、日付、数値をあらかじめ処理し文字列変換した変数を+で繋げる方法。
  • %書式、”安全性評価:%c等級” % rank、のような形。「%c」はフォーマット指定子。
  • formatメソッド、今回の大メインクライマックス。

format()によるフォーマット方法

文字列のフォーマット書式

フォーマットは「置換フィールド」と「format()」によって成り立つ。

置換フィールドとは{}(鉤括弧)のこと。書式は大まかには、{インデックス !変換 : 書式}

format()は、置換フィールドを含む文字列対して利用する。書式はソースコードを見た方が早いが5つほど構成する要素がある。それは「文字よせ」「最小幅」「小数点以下の桁数」「日付型用の%Dなど」「型の指定」。

format()、実証ソースコード

インデックスを指定するフォーマット方法

# インデックス指定1
"安全性能:{0}、運動性能:{1}、燃費性能:{2}".format("A", "B", "C")
# インデックス指定2
"安全性能:{0}、運動性能:{1}、燃費性能:{2}".format("C", "A", "B")
# インデックス指定3
"安全性能:{2}、運動性能:{1}、燃費性能:{1}".format("C", "A", "B")
# インデックス指定しない1
"安全性能:{}、運動性能:{}、燃費性能:{}".format("A", "B", "C")
# インデックス指定しない2
"安全性能:{}、運動性能:{}、燃費性能:{}".format("A", "C", "B")
# 同じものを何回指定してもOK1
"{0}{0}{0}{1}{1}{1}{2}{2}{2}".format("A", "C", "B")

# シーケンスをアンパック
"安全性能:{2}、運動性能:{1}、燃費性能:{0}".format(*"ACB")
listed_str = ["A", "B", "C"]
"安全性能:{2}、運動性能:{0}、燃費性能:{1}".format(*listed_str)
# 同じものを何回指定してもOK2
"{0}{0}{0}{1}{1}{1}{2}{2}{2}".format(*listed_str)

インデックス指定はそのまま指定したものが出てくるので好きなところに好きなだけ出せます。指定しないと引数の位置が一致したものが出てきますね。リストの可変長引数はこういうところで役立ちますね。

キーを指定するフォーマット方法

# キーと値をメソッドに渡す
"総合得点::レガシィB4:{legacy}_レヴォーグ:{levorg}_WRX S4:{wrx_s4}".format(legacy="987", levorg="986", wrx_s4="985")
# 辞書を渡してアンパック
dict_score = {"egacy":"987", "levorg":"986", "wrx_s4":"985"}
"総合得点::レガシィB4:{legacy}_レヴォーグ:{levorg}_WRX S4:{wrx_s4}".format(**dict_score)

# 引数の属性へのアクセス(複素数のモジュール、cmathを使ってみる)
# cmathの属性である、realとimagを呼び出せる
cmath_num = 8-8j
"複素数::{0}_実部:{0.real}_虚部{0.imag}".format(cmath_num)

# 引数の要素へのアクセス
list_fruits = ["apple", "mango", "ichigo", "banana", "mikan", "satsumaimo"]
"赤い果物:{0[1]}、黄色い果物:{1[2]}".format(list_fruits)

# 変換フラグを使う。!sはstr()、!rはrepr()、!aはascii()
"str(){!s}, repr(){!r}, ascii(){!a}".format(1234, "1,234", "2345円")

# 文字よせ、<>^が寄せの指定、後ろの数字は文字数
"{:<50}".format("左寄せ")
"{:>50}".format("右寄せ")
"{:^50}".format("中央寄せ")
 # 寄せの指定の前の記号で残りの文字を埋める
"{:@^50}".format("中央寄せ")

引数の属性へアクセスできるのはどこかで役に立ちそう。フォーマットがそこまでできるとは初耳。Pythonだけ? 変換フラグについてはstr()は文字列にできるからよく使うと思う。他は正直2byte文字の言語圏の国だから使わないかもしれない。文字の寄せは、ブラウザだとCSSに任せろよ。と思う。

数値型の表現方法

# 数値ように符号の表示を指定できる。(マイナスは外せない。)
"{:+f}; {:+f}".format(10, -20)
"{: f}; {: f}".format(10, -20) 
"{:-f}; {:-f}".format(10, -20) 

# 2進数、8進数、10進数、16進数
"2進数:{0:b}, 8進数:{0:o}, 10進数:{0:d}, 16進数:{0:x}".format(2501)
"2進数:{0:b}, 8進数:{0:o}, 10進数:{0:d}, 16進数:{0:x}".format(1010)
# プレフィックス付きにする
"2進数:{0:#b}, 8進数:{0:#o}, 10進数:{0:d}, 16進数:{0:#x}".format(2501)

# カンマ付き
"{:,}".format(25012501)
# パーセント付き、小数点の桁数も指定
"{:.3%}".format(100 / 3)

符号をつけらるのはいいけど使い所がいまいち分からない。その次のは2進数とかに直して表示したいときとか使えて便利。プレフィックスは16進数はhじゃなくてxだったことが分かって勉強になります。確かに0xで始まるからな。づっとxの意味がわからなかったがhexのxだったのか。

日付型の表現方法

# 年月日時分秒
date = datetime.datetime(2054, 11, 11, 12, 20, 55)
'{:%Y-%m-%d %H:%M:%S}'.format(d)

Pythonの標準ライブラリの「datetime型」では、書式コード(%Yとか%S)は全て「0埋め」されるものばかり。01月07日という形になるので、1月7日としたい場合は他の方法を考えないといけない。0埋めしないモジュールもどっかにあるかも。

フォーマットの割と新しい書き方

name = "Kazundo Gouda"
# Python3.6以降 format()が不要
f"My name is{name}"
# Python3.8以降 format()が不要、変数名=変数の中身という形で出力
f"My name is{name=}"

3.6からformat()をリテラルに繋げて書かなくても良くなt多用です。前もってフォーマットした値を変数に入れておけばソースコードも見やすくなるかな。

format()、実行結果

フォーマット実行結果1

%を指定すると割合を計算して表示してくれるので、100➗3は 3333.333%になってしまう。

フォーマット実行結果2

様々なフォーマットの方法を取り上げてみたが、一番使うのは数値や金額日付や時刻になると思う。

フォーマットに直接関係ないが、PEPによるとソースコードの1行の最大文字数は79文字までにするべきだということです。コーディング規約を矯正してくれる「lake8 」「yapf」「futures」のモジュールを利用しているので79文字を超えるとエラーみたいに教えてくれる。

次回は正規表現を扱いたい。ではまた。

コメントする