Python, formatで書式変換(0埋め、指数表記、16進数など)
Pythonで数値や文字列を様々な書式に変換(フォーマット)するには、組み込み関数format()
または文字列メソッドstr.format()
を使う。
なお、Python3.6から文字列メソッドstr.format()
をより簡潔に記述できるf文字列(f-strings)が追加された。以下の記事を参照。
組み込み関数 format()
組み込み関数としてformat()
が提供されている。
第一引数に元の文字列str
や数値int
, float
など、第二引数に書式指定文字列を指定すると、書式化された文字列str
が返される。
例を示す。書式指定文字列の書き方については後述。
i = 255
print(format(i, '#04x'))
print(type(format(i, '#04x')))
# 0xff
# <class 'str'>
s = 'abc'
print(format(s, '*^10'))
# ***abc****
文字列メソッド str.format()
文字列str
のメソッドにもformat()
がある。
format()
メソッドを呼び出す文字列str
内の{}
は置換フィールドと呼ばれ、format()
メソッドの引数に置き換えられる。書式指定文字列は置換フィールド{}
内に:
に続けて記述する。返り値は書式化された文字列str
。
上述の組み込み関数format()
の例と等価な処理は以下のようになる。
print('{:#04x}'.format(i))
print(type('{:#04x}'.format(i)))
# 0xff
# <class 'str'>
print('{:*^10}'.format(s))
# ***abc****
置換フィールド{}
に対する引数の指定
順番通りに引数を指定(デフォルト)
置換フィールド{}
は複数存在してもよい。デフォルトではformat()
の引数が順番に挿入される。
print('{}-{}-{}'.format(255, 'abc', 1.23))
# 255-abc-1.23
{}
の数が少ない場合は余分な引数は無視され、{}
の数が多い(引数が足りない)場合はエラーになる。
print('{}-{}'.format(255, 'abc', 1.23))
# 255-abc
# print('{}-{}-{}-{}'.format(255, 'abc', 1.23))
# IndexError: Replacement index 3 out of range for positional args tuple
整数値に対して位置引数を指定
{0}
や{1}
のように{}
内に整数値を指定すると引数の順番に応じて出力される。同じ番号を繰り返し使うこともできる。文字列中に同じ値を挿入したい場合に便利。
print('{0}-{1}-{0}'.format(255, 'abc'))
# 255-abc-255
任意の名前(文字列)に対してキーワード引数を指定
{}
内に任意の名前を指定し、format()
にキーワード引数として指定することも可能。
print('{name} is {age} years old.'.format(name='Alice', age=20))
# Alice is 20 years old.
リスト、辞書を引数に指定
リストや辞書もformat()
の引数に指定できる。
置換フィールド内でリストのインデックスや辞書のキーを[]
で指定する。辞書のキーの指定では引用符'
や"
は使わないので注意。
l = ['one', 'two', 'three']
print('{0[0]}-{0[1]}-{0[2]}'.format(l))
# one-two-three
d1 = {'name': 'Alice', 'age': 20}
d2 = {'name': 'Bob', 'age': 30}
print('{0[name]} is {0[age]} years old.\n{1[name]} is {1[age]} years old.'.format(d1, d2))
# Alice is 20 years old.
# Bob is 30 years old.
リストに*
をつけて引数に指定することで位置引数として展開したり、辞書に**
をつけて引数に指定することでキーワード引数として展開することも可能。
l = ['one', 'two', 'three']
print('{}-{}-{}'.format(*l))
# one-two-three
d = {'name': 'Alice', 'age': 20}
print('{name} is {age} years old.'.format(**d))
# Alice is 20 years old.
波括弧の記述(エスケープ)
format()
を呼び出す文字列の中で波括弧{
, }
を書きたい場合は{{
, }}
のように2回繰り返して書く。バックスラッシュ\
ではエスケープできないので注意。
print('{{}}-{num}-{{{num}}}'.format(num=100))
# {}-100-{100}
書式指定文字列
いずれの場合も、書式を指定するには{}
内の整数値や名前の文字列のあと:書式指定文字列
のように書く。詳細は次に説明する。
print('{num} = {num:#x} = {num:#b}'.format(num=255))
# 255 = 0xff = 0b11111111
format()
での書式指定文字列の例
組み込み関数format()
および文字列メソッドstr.format()
では書式指定文字列で書式を指定する。
以下、書式指定文字列の例を紹介する。サンプルコードでは文字列メソッドstr.format()
を使うが、組み込み関数format()
でも同様。組み込み関数format()
では第二引数に書式指定文字列を指定する。
左寄せ、中央寄せ、右寄せ: <
, ^
, >
, =
<
、^
、>
で左寄せ、中央寄せ、右寄せなどのアラインメントができる。全体の文字数を数値で指定する。
print('left : {:<10}'.format(100))
print('center: {:^10}'.format(100))
print('right : {:>10}'.format(100))
# left : 100
# center: 100
# right : 100
埋める文字を指定することもできる。上の例のように省略するとスペース。例は省略するが、一文字であれば全角でもよい。
print('left : {:*<10}'.format(100))
print('center: {:*^10}'.format(100))
print('right : {:*>10}'.format(100))
# left : 100*******
# center: ***100****
# right : *******100
>
による右寄せは符号(-
, +
)が考慮されない。=
を使うと符号のあとから指定した文字で埋められる。符号処理の詳細は後述。
print('sign: {:0>10}'.format(-100))
print('sign: {:0=10}'.format(-100))
# sign: 000000-100
# sign: -000000100
<
、^
、>
は文字列に対しても指定できるが、=
はエラーValueError
になる。文字列に対して=
で処理したい場合はint()
やfloat()
などで数値に変換する必要がある。
# print('sign: {:0=10}'.format('-100'))
# ValueError: '=' alignment not allowed in string format specifier
print('sign: {:0=10}'.format(int('-100')))
# sign: -000000100
左寄せ、中央寄せ、右寄せについてはljust()
, center()
, rjust()
という専用の文字列メソッドもある。以下の記事を参照。
ゼロ埋め
ゼロ埋めして桁数を合わせたい場合は埋める文字を0
として右寄せする。
ゼロ埋めの場合はアラインメント記号を省略すると=
を指定したものとして処理される。
print('zero padding: {:0=10}'.format(100))
print('zero padding: {:010}'.format(100))
# zero padding: 0000000100
# zero padding: 0000000100
print('zero padding: {:0=10}'.format(-100))
print('zero padding: {:010}'.format(-100))
# zero padding: -000000100
# zero padding: -000000100
=
として処理されるので、上述のように引数に文字列を指定するとエラーになってしまう。注意。
# print('zero padding: {:010}'.format('-100'))
# ValueError: '=' alignment not allowed in string format specifier
ゼロ埋めについてはzfill()
という専用の文字列メソッドもある。以下の記事を参照。
符号(プラス、マイナス): +
, スペース
デフォルトでは負の値にのみ符号(マイナス-
)が表示される。
書式化指定文字列に+
をつけると正の数にも符号(プラス+
)が表示される。スペースをつけると正の数の先頭に一文字分のスペースが表示され、負の数と桁数が揃う。
print('sign: {}'.format(100))
print('sign: {}'.format(-100))
# sign: 100
# sign: -100
print('sign: {:+}'.format(100))
print('sign: {:+}'.format(-100))
# sign: +100
# sign: -100
print('sign: {: }'.format(100))
print('sign: {: }'.format(-100))
# sign: 100
# sign: -100
上述のゼロ埋めなど任意の文字で埋める場合は注意が必要。+
もスペースもつけないデフォルトでは正の数が一文字多く埋められてしまう。
print('sign: {:06}'.format(100))
print('sign: {:06}'.format(-100))
# sign: 000100
# sign: -00100
print('sign: {:+06}'.format(100))
print('sign: {:+06}'.format(-100))
# sign: +00100
# sign: -00100
print('sign: {: 06}'.format(100))
print('sign: {: 06}'.format(-100))
# sign: 00100
# sign: -00100
アラインメント記号を使う場合は、アラインメント記号のあとに符号の指定記号を書く。
print('sign: {:*>6}'.format(100))
print('sign: {:*>6}'.format(-100))
# sign: ***100
# sign: **-100
print('sign: {:*>+6}'.format(100))
print('sign: {:*>+6}'.format(-100))
# sign: **+100
# sign: **-100
print('sign: {:*> 6}'.format(100))
print('sign: {:*> 6}'.format(-100))
# sign: ** 100
# sign: **-100
桁区切り(カンマ、アンダースコア): ,
, _
3ケタ毎にカンマ,
またはアンダースコア_
の区切りを入れる。大きい数値が見やすくなる。なお、アンダースコア_
はPython3.6で追加されたオプションなので、それより前のバージョンでは使えない。
print('{:,}'.format(100000000))
print('{:_}'.format(100000000))
# 100,000,000
# 100_000_000
浮動小数点数float
の場合は整数部にのみ区切りが入る。
print('{:,}'.format(1234.56789))
print('{:_}'.format(1234.56789))
# 1,234.56789
# 1_234.56789
2進数、8進数、16進数: b
, o
, x
, X
数値を2進数、8進数、16進数に変換して出力する。
b
: 2進数o
: 8進数x
,X
: 16進数(大文字だとアルファベットが大文字表記)
print('bin: {:b}'.format(255))
print('oct: {:o}'.format(255))
print('hex: {:x}'.format(255))
print('HEX: {:X}'.format(255))
# bin: 11111111
# oct: 377
# hex: ff
# HEX: FF
ゼロ埋めと組み合わせることも可能。2進数や16進数表記で桁を合わせるためによく使われる。
print('bin: {:08b}'.format(255))
print('oct: {:08o}'.format(255))
print('hex: {:08x}'.format(255))
print('HEX: {:08X}'.format(255))
# bin: 11111111
# oct: 00000377
# hex: 000000ff
# HEX: 000000FF
書式化指定文字列の先頭に#
をつけると、0b
や0x
などの接頭辞が加えられる。0埋めの文字数は接頭辞も考慮して指定する必要があるので注意。
print('bin: {:#b}'.format(255))
print('oct: {:#o}'.format(255))
print('hex: {:#x}'.format(255))
print('HEX: {:#X}'.format(255))
# bin: 0b11111111
# oct: 0o377
# hex: 0xff
# HEX: 0XFF
print('bin: {:#010b}'.format(255))
print('oct: {:#010o}'.format(255))
print('hex: {:#010x}'.format(255))
print('HEX: {:#010X}'.format(255))
# bin: 0b11111111
# oct: 0o00000377
# hex: 0x000000ff
# HEX: 0X000000FF
2進数や16進数ではアンダースコア_
の桁区切りのみ挿入できる(Python3.6以降)。4ケタ区切りとなる。ゼロ埋めの文字数はアンダースコアの数も考慮する必要がある。
print('hex: {:08x}'.format(255))
print('hex: {:09_x}'.format(255))
print('hex: {:#011_x}'.format(255))
# hex: 000000ff
# hex: 0000_00ff
# hex: 0x0000_00ff
2進数や16進数に書式を変換できるのは整数int
のみ。中身が数字であっても文字列str
だとエラーValueError
になる。int()
で数値に変換すればよい。
# print('hex: {:08x}'.format('255'))
# ValueError: Unknown format code 'X' for object of type 'str'
print('hex: {:08x}'.format(int('255')))
# hex: 000000ff
Pythonにおける2進数、8進数、16進数の数値・文字列の変換についての詳細は以下の記事を参照。
小数点以下の桁数指定(固定小数点表記): f
, F
浮動小数点数float
を文字列str
に変換すると、値によって自動で指数表記になるが、書式化指定文字列にf
を指定するとならない。f
は"Fixed-point notation"(固定小数点表記)の意。
print('{}'.format(0.00001234))
print('{}'.format(12340000000000000.0))
print('{:f}'.format(0.00001234))
print('{:f}'.format(12340000000000000.0))
# 1.234e-05
# 1.234e+16
# 0.000012
# 12340000000000000.000000
常に指数表記に変換したい場合は後述のe
, E
を使う。
上の例のように、デフォルトは小数点以下6桁になる。小数点以下の桁数(精度)を指定するには、.[桁数]f
とする。整数部の桁数によらず小数点以下が指定した桁数になる。
print('{:.2f}'.format(123.456))
print('{:.5f}'.format(123.456))
print('{:.3f}'.format(0.0001234))
# 123.46
# 123.45600
# 0.000
出力が元の桁数よりも少ない桁数になると値が丸められる。四捨五入ではなく偶数への丸めなので注意。0.5
が0
に丸められたりする。
print('{:.0f}'.format(0.4))
print('{:.0f}'.format(0.5))
print('{:.0f}'.format(0.6))
# 0
# 0
# 1
一般的な四捨五入にしたい場合は標準ライブラリdecimalのquantize()
メソッドを使う方法がある。以下の記事を参照。
浮動小数点数float
が取り得る最大値を超える値は自動的に無限大inf
として扱われる。F
とすると大文字のINF
と出力される。F
の場合、非数も大文字NAN
になる。
print('{:.5f}'.format(10e1000))
print('{:.5F}'.format(10e1000))
# inf
# INF
指数表記: e
, E
書式化指定文字列にe
またはE
を指定すると常に指数表記に変換される。e
だと出力も小文字のe
、E
だと出力も大文字のE
になる。
print('{:e}'.format(0.0001234))
print('{:E}'.format(0.0001234))
# 1.234000e-04
# 1.234000E-04
小数点以下の桁数を指定することも可能。整数部が1桁で小数点以下が指定した桁数になる。
print('{:.5e}'.format(0.0001234))
print('{:.2e}'.format(0.0001234))
# 1.23400e-04
# 1.23e-04
print('{:.5e}'.format(987.65))
print('{:.2e}'.format(987.65))
# 9.87650e+02
# 9.88e+02
左寄せ、中央寄せ、右寄せ、ゼロ埋めの指定をした場合、e
, E
, +
, -
も文字数にカウントされるので注意。
print('{:>12.5e}'.format(987.65))
print('{:012.2e}'.format(987.65))
# 9.87650e+02
# 00009.88e+02
有効数字(有効桁数): g
, G
g
は"General format"(一般書式?)で、値によって固定小数点表記と指数表記が自動で切り替わる。
print('{:g}'.format(0.0001234))
print('{:g}'.format(0.00001234))
# 0.0001234
# 1.234e-05
.[桁数]g
とすると有効数字(有効桁数)を指定できる。小数点以下の桁数ではないので注意。結果によって自動で指数表記になる。
print('{:.2g}'.format(123.456))
print('{:.3g}'.format(123.456))
print('{:.8g}'.format(123.456))
print('{:.3g}'.format(0.0001234))
# 1.2e+02
# 123
# 123.456
# 0.000123
上の例のようにデフォルトでは小数点以下の末尾の0
は省略される。#
をつけると省略されない。整数の場合も末尾に小数点がつく。
print('{:#.2g}'.format(123.456))
print('{:#.3g}'.format(123.456))
print('{:#.8g}'.format(123.456))
print('{:#.3g}'.format(0.0001234))
# 1.2e+02
# 123.
# 123.45600
# 0.000123
g
を省略してもほとんどの場合で同じ結果だが、整数で出力される場合は異なる。
print('{:.2}'.format(123.456))
print('{:.3}'.format(123.456))
print('{:.8}'.format(123.456))
print('{:.3}'.format(0.0001234))
# 1.2e+02
# 1.23e+02
# 123.456
# 0.000123
print('{:#.2}'.format(123.456))
print('{:#.3}'.format(123.456))
print('{:#.8}'.format(123.456))
print('{:#.3}'.format(0.0001234))
# 1.2e+02
# 1.23e+02
# 123.45600
# 0.000123
同じ値をf
, e
, g
, 省略した場合で処理するとそれぞれ以下のようになる。
print('{:.3f}'.format(123.456))
print('{:.3e}'.format(123.456))
print('{:.3g}'.format(123.456))
print('{:.3}'.format(123.456))
# 123.456
# 1.235e+02
# 123
# 1.23e+02
print('{:.8f}'.format(123.456))
print('{:.8e}'.format(123.456))
print('{:.8g}'.format(123.456))
print('{:.8}'.format(123.456))
# 123.45600000
# 1.23456000e+02
# 123.456
# 123.456
様々な大きさの値を決まった桁数・幅で出力したい場合は、e
またはE
の指数表記を使う。
print('{:.4e}'.format(123.456))
print('{:.4e}'.format(0.000012345))
print('{:.4e}'.format(12))
# 1.2346e+02
# 1.2345e-05
# 1.2000e+01
なお、g
ではなくG
を使うと、指数表記や無限大、非数が、E
, INF
, NAN
のように大文字になる。
print('{:.2g}'.format(123.456))
print('{:.2g}'.format(10e1000))
print('{:.2G}'.format(123.456))
print('{:.2G}'.format(10e1000))
# 1.2e+02
# inf
# 1.2E+02
# INF
パーセント表示: %
書式化指定文字列に%
を指定すると、float
またはint
の値を100倍して%
を付けた文字列に変換する。
小数点以下の桁数を指定することも可能。デフォルトでは小数点以下が6桁。左寄せ、中央寄せ、右寄せ、ゼロ埋めもできる。%
も文字数にカウントされる。
print('{:%}'.format(0.12345))
print('{:.2%}'.format(0.12345))
# 12.345000%
# 12.35%
print('{:%}'.format(10))
print('{:.2%}'.format(10))
# 1000.000000%
# 1000.00%
print('{:>10.2%}'.format(0.12345))
print('{:010.2%}'.format(0.12345))
# 12.35%
# 000012.35%
日時(datetime)
書式化指定文字列にはdatetimeモジュールのdatetime
, date
, time
オブジェクトに対する書式化コードも指定可能。datetimeモジュールの詳細は以下の記事を参照。
import datetime
dt = datetime.datetime(2020, 1, 5, 20, 15, 30)
print('datetime: {}'.format(dt))
# datetime: 2020-01-05 20:15:30
print('datetime: {:%A, %m/%d/%Y %I:%M:%S %p}'.format(dt))
# datetime: Sunday, 01/05/2020 08:15:30 PM
print('datetime: {}'.format(dt.isoformat()))
# datetime: 2020-01-05T20:15:30
最後の例のように、ISO 8601形式の文字列に変換する場合は書式化コードを指定するよりisoformat()
メソッドを使う方が楽。