かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Python3 文字列中に変数展開したい

1. %演算子

変換指定子 フォーマット型
%f 浮動小数点数
%d 整数
%s 文字列
%x 16進数
%o 8進数
%% %
print( 'Hello %s!' % 'World' )
# => Hello World
area = 3.14 * 5 * 5
print( '円の面積は%f平方cm' % area )
# => 円の面積は78.500000平方cm
cat = 3
dog = 6
print( 'cats are %d, dogs are %f' % (cat, dog) )
# => cats are 3, dogs are 6.000000

2. str.format()

str.format(*args, **kwargs)
置換フィールドは位置引数のインデックスナンバー、または、キーワード引数の名前を含みます。返り値は、それぞれの置換フィールドが対応する引数の文字列値で置換された文字列のコピーです。
出典: str.format - 4. 組み込み型 — Python 3.6.5 ドキュメント

引数の順序で指定

'{0}年{1}月{2}日'.format(2018, 8, 15)
# => 2018年8月15日

キーワードで指定

'{year}年{month}月{day}日'.format(year=2018, month=8, day=15)
# => 2018年8月15日

リスト・辞書

リスト

l = ['Mika', 'boss', 18]
'{0[0]}-{0[1]}-{0[2]}'.format(l)
# => Mika-boss-18

辞書

d = {'name': 'Aki', 'role': 'gunner', 'age': 17}
'{0[name]}-{0[role]}-{0[age]}'.format(d)
# => Aki-gunner-17

※ リストも辞書もformat()引数の位置を指定する必要がある。下記のような記述はエラーになる

l = ['Mika', 'boss', 18]
'{[0]}-{[1]}-{[2]}'.format(l)
# => エラー

位置引数・キーワード引数でリスト・辞書を展開して渡す

リスト => 位置引数*

l = ['Mika', 'boss', 18]
'{0}: {1}-{2}-{3}'.format('Keizoku', *l)
# => Keizoku: Mika-boss-18

辞書 => キーワード引数**

d = {'name': 'Aki', 'role': 'gunner', 'age': 17}
'{0}: {name}-{role}-{age}'.format('Keizoku' ,**d)
# => Keizoku: Aki-gunner-17

3. f-string (formatted string literal)

バージョン 3.6 で追加.
フォーマット済み文字列リテラル( formatted string literal )または f-string は、接頭辞 'f' または 'F' の付いた文字列リテラルです。これらの文字列には、波括弧 {} で区切られた式である置換フィールドを含めることができます。他の文字列リテラルの場合は内容が常に一定で変わることが無いのに対して、フォーマット済み文字列リテラルは実行時に式として評価されます。
出典: 2.4.3. フォーマット済み文字列リテラル

val = 'Wold'
f'Hello {val}!'
# => Hello Wold!

# リスト
l = ['Mika', 'boss', 18]
f'{l[0]}-{l[1]}-{l[2]}'
# => Mika-boss-18

# 辞書
d = {'name': 'Aki', 'role': 'gunner', 'age': 17}
f'{d["name"]}-{d["role"]}-{d["age"]}'
# => Aki-gunner-17

f'{d[name]}-{d[role]}-{d[age]}'
# => NameError: name 'name' is not defined

※ 辞書のキーは"(ダブルコーテーション)で囲わないとエラーになる。str.format()は囲わなくてもOKなのでハマりどころかもしれません。

{}内での計算

f-stringは{}内が先に計算された後に文字列展開される

val = 1.41421356
size = 4
f'res: {val:.{size}}'
# => res: 1.414

val = 2
f'Square {val*2}'
# => Square 4

{}内で関数も実行できる

def add(a, b):
  return a + b
x = 10
y = 20
f'value: {add(x, y)}'
# => value: 30

{ } を出力する

\ではなく、{{ }}の様に二重で囲むと{ }が出力できる

val = 100
f'{{}}-{val}-{{val}}-{{{val}}}-{{'
# => {}-100-{val}-{100}-{

※ 片方だけ{を出力したい場合も二重にしないとシンタックスエラーになる

書式の指定

展開する変数に:~で書式を指定して展開することが出来るようです。

num = 255
print( f'{num} to hex => {num:x}' )
# => 255 to hex => ff

d = {'year': 2018, 'month': 8, 'day': 15}
print( f'{d["year"]}-{d["month"]:02}-{d["day"]:02}' )
# => 2018-08-15

 
Pythonって書き方は1つのようなイメージがあったんのですが、文字列中の変数展開の方法も結構いろいろあるんだなと知る事ができました。
Python3からは基本的に、f-string (f'...')で良いかなという印象です。
展開する変数が配列や辞書の時は場合によってはstr.formatで位置引数(*)・キーワード引数(**)を使うほうが楽かもしれません。


[参考]

ゼロから作るDeep Learning ? ―自然言語処理編

ゼロから作るDeep Learning ? ―自然言語処理編