今さらPython3 (45) - 書式設定
第7章を読み進めてます。
%なんちゃら
すでに何回か使ってきたけど、%sとかの話。
>>> '%s' % 42 '42' >>> '%d' % 42 '42' >>> '%x' % 42 '2a' >>> '%o' % 42 '52'
%sのところに%の後ろにあるデータを差し込んで表示するというもの。42を文字列(%s)、10進数(%d)、16進数(%x)、8進数(%o)で表示している。
>>> '%s' % 7.03 '7.03' >>> '%f' % 7.03 '7.030000' >>> '%e' % 7.03 '7.030000e+00' >>> '%g' % 7.03 '7.03'
これらは、最初の%sは文字列で再出。10進float形式(%f)、指数形式(%e)、ケタの大きさによって表示がfloatか指数に変わる形式(%g)を使っている。
>>> '%d%%' % 100 '100%' >>> '%d%' % 100 Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: incomplete format >>> '%d%%' % 100 '100%'
これを見る限り、%という字を表示するために%%と入れているんだね。
>>> actor = 'Richard Gere' >>> cat = 'Chester' >>> weight = 28 >>> "My wife's favorite actor is %s" % actor "My wife's favorite actor is Richard Gere" >>> "Our cat %s weighs %s pounds" % (cat, weight) 'Our cat Chester weighs 28 pounds' >>>
%sの場所に文字列を挿入するのが決まりで、% に続けて%sの部分に入れる値を書いてやる。ただし、複数ある場合は括弧で囲んでタプルにしなさいてな具合。
>>> n = 42 >>> f = 7.03 >>> s = 'string cheese' >>> '%d %f %s' % (n, f, s) '42 7.030000 string cheese' >>> '%10d %10f %10s' % (n, f, s) ' 42 7.030000 string cheese' >>> '%-10d %-10f %-10s' % (n, f, s) '42 7.030000 string cheese'
出力幅を固定したいときは、%の後ろに数字を入れる。基本右詰だけど、左詰にしたいときは負の値を入れる。でも、string cheeseは10文字超えているけど全部出ているし、これだとどっちに寄っているか分からない。
>>> '%-10d %-10f %20s' % (n, f, s) '42 7.030000 string cheese' >>> '%-10d %-10f %-20s' % (n, f, s) '42 7.030000 string cheese '
文字列の場合も原則右詰は同じということだね。
>>> '%10.4d %10.4f %10.4s' % (n, f, s) ' 0042 7.0300 stri' >>> '%.4d %.4f %.4s' % (n, f, s) '0042 7.0300 stri'
ドット(.)の後ろの数字を使って表現するのは、出力幅の上限。ただしfloatの場合は小数点以下の桁数となる。
>>> '%*.*d %*.*f %*.*s' % (10, 4, n, 10, 4, f, 10, 4, s) ' 0042 7.0300 stri'
表示幅などの情報を変数化したいときは*を使う。
新しいフォーマット
古いフォーマットというのは、これまで何となく触ったことあったけど、これからやるのは初めて(意識して)見るスタイル。Python3以降しか使わないなら、むしろこの新しい方を覚えた方が良さそう。
>>> '{} {} {}'.format(n, f, s) '42 7.03 string cheese'
%なんちゃらよりは直感的に分かりやすいかも。
>>> '{2} {0} {1}'.format(f,s,n) '42 7.03 string cheese' >>> '{4} {5} {20}'.format(f,s,n) Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: tuple index out of range
{}の中の数字はどういう意味かを考える上での実験。n->f->sの順で出力されているので、format()の中のインデックスを示しているという理解で良さそう。
>>> '{n} {f} {s}'.format(n=42, f=7.03, s='string cheese') '42 7.03 string cheese'
これの方が分かりやすい。
>>> d = {'n':42, 'f':7.03, 's':'string cheese'} >>> '{0[n]} {0[f]} {0[s]} {1}'.format(d, 'other') '42 7.03 string cheese other'
ここは、本の誤植でしょ。解説の説明の通りにするなら、上みたいな書き方をする必要があるはず。format()中に2つの引数があって、最初の3つは0なので、dという辞書のキーを指定している。4つ目(最後)のotherはformat()の中にある2つめの引数なので、インデックス的には1を使っているのでこうなる。このフォーマットなら辞書が入れ子になっていても行けそうな気がする。
>>> '{0:d} {1:f} {2:s}'.format(n, f, s) '42 7.030000 string cheese' >>> '{n:d} {f:f} {s:s}'.format(n=43, f=7.04, s='string cheeese') '43 7.040000 string cheeese' >>> n 42 >>> f 7.03 >>> s 'string cheese' >>>
%d, %f, %sなどの代わりに:d, :f, :sを使いますということは、これまでのオプションも使えるという確認。
>>> '{0:10d} {1:10f} {2:10s}'.format(n, f, s) ' 42 7.030000 string cheese' >>> '{0:10d} {1:10f} {2:10s}'.format(n, f, s) ' 42 7.030000 string cheese' >>> '{0:>10d} {1:>10f} {2:>10s}'.format(n, f, s) ' 42 7.030000 string cheese' >>> '{0:<10d} {1:<10f} {2:<10s}'.format(n, f, s) '42 7.030000 string cheese' >>>
ただし右寄せ左寄せは不等号(<>)を使う事で分かりやすくなったね。
>>> '{0:^10d} {1:^10f} {2:^10s}'.format(n, f, s) ' 42 7.030000 string cheese'
センタリングもあるのね。
>>> '{0:>10.4d} {1:>10.4f} {2:10.4s}'.format(n, f, s) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: Precision not allowed in integer format specifier >>> '{0:>10d} {1:>10.4f} {2:10.4s}'.format(n, f, s) ' 42 7.0300 stri '
ここは仕様が変わったとは言え、整数値にマスキングするケースって、あまりイメージできないので気にしなくても良さげ。
(つづく)