python-3.xで辞書を使用して文字列をフォーマットするにはどうすればよいですか?


215

私は辞書を使用して文字列をフォーマットするのが大好きです。これは、使用している文字列形式を読み取ったり、既存の辞書を利用したりするのに役立ちます。例えば:

class MyClass:
    def __init__(self):
        self.title = 'Title'

a = MyClass()
print 'The title is %(title)s' % a.__dict__

path = '/path/to/a/file'
print 'You put your file here: %(path)s' % locals()

ただし、同じことを行うためのpython 3.x構文を理解することはできません(またはそれが可能な場合でも)。次のことを行いたい

# Fails, KeyError 'latitude'
geopoint = {'latitude':41.123,'longitude':71.091}
print '{latitude} {longitude}'.format(geopoint)

# Succeeds
print '{latitude} {longitude}'.format(latitude=41.123,longitude=71.091)

回答:


15

質問はPython 3に固有なので、ここではPython 3.6以降で利用可能な新しいf-string構文を使用します。

>>> geopoint = {'latitude':41.123,'longitude':71.091}
>>> print(f'{geopoint["latitude"]} {geopoint["longitude"]}')
41.123 71.091

外側の単一引用符と内側の二重引用符に注意してください(逆にすることもできます)。


f-stringの使用はpython3のアプローチにより整合していると思います。
Jonatas CD、2018

2
f-stringはPython 3.6の新機能であり、3.5の新機能ではないことに注意してください。
Hugo

409

これはいいですか

geopoint = {'latitude':41.123,'longitude':71.091}
print('{latitude} {longitude}'.format(**geopoint))

2
これを試してみましたが、うまくいきました。しかし、「ポインタ表記」の使い方がわかりません。Pythonがポインタを使用しないことは知っていますが、これはクワーグの例ですか?
Homunculus Reticulli

2
@HomunculusReticulliこれは形式パラメーター(最小フィールド幅)であり、ポインターC ++スタイルへのポインターではありません。docs.python.org/release/2.4.4/lib/typesseq-strings.html
D.Rosado

29
Python 3.2が導入されましたformat_mapに似ていますがstr.format(**mapping)mapping直接使用され、にコピーされませんdict。これは、たとえばmappingdictサブクラスの場合に役立ちます
ダイアピル2015年

1
@eugene **はPython辞書に対して何をしますか?print(** geopoint)が構文エラーを出さないためオブジェクトを作成するとは思いません
Nityesh Agarwal

4
@NityeshAgarwal print(**geopoint)は、個々の引数としてname = valueペアを使用してディクショナリを展開しprint(longitude=71.091, latitude=41.123)ます。つまり、と同じです。多くの言語では、それはsplatオペレーターとして知られています。JavaScriptでは、スプレッドオペレーターと呼ばれます。Pythonでは、この演算子に特定の名前は付けられていません。
abhisekp

79

辞書をキーワード引数にアンパックするには、を使用します**。また、新しいスタイルのフォーマットは、オブジェクトの属性とマッピングのアイテムの参照をサポートします。

'{0[latitude]} {0[longitude]}'.format(geopoint)
'The title is {0.title}s'.format(a) # the a from your first example

2
プレースホルダーの位置インデックスを追加すると、コードがより明確になり、使いやすくなるので、私はこの答えをよりよく見つけます。:1は、このような何かがある場合は特に'{0[latitude]} {1[latitude]} {0[longitude]} {1[longitude]}'.format(geopoint0, geopoint1)
Løiten

1
これは、a defaultdictを使用していて、すべてのキーを持っていない場合に便利です
Whymarrh

65

Python 3.0および3.1はEOL済みであり、誰も使用していないため、str.format_map(mapping)(Python 3.2+)を使用でき、使用する必要があります。

に似ていますがstr.format(**mapping)マッピングは直接使用され、にはコピーされませんdict。これは、たとえばマッピングがdictサブクラスである場合に役立ちます。

これが意味することは、たとえば、defaultdict欠落しているキーのデフォルト値を設定(および返す)することができるということです。

>>> from collections import defaultdict
>>> vals = defaultdict(lambda: '<unset>', {'bar': 'baz'})
>>> 'foo is {foo} and bar is {bar}'.format_map(vals)
'foo is <unset> and bar is baz'

提供されたマッピングが dictサブクラスではなくであっとしても、これはおそらくわずかに速いでしょう。

与えられた違いは、しかし、大きくはありません

>>> d = dict(foo='x', bar='y', baz='z')

その後

>>> 'foo is {foo}, bar is {bar} and baz is {baz}'.format_map(d)

よりも約10 ns(2%)速い

>>> 'foo is {foo}, bar is {bar} and baz is {baz}'.format(**d)

私のPython 3.4.3で。辞書にあるキーが多いほど、その差は大きくなるでしょう。


ただし、フォーマット言語はそれよりもはるかに柔軟です。インデックス付きの式や属性アクセスなどを含めることができるため、オブジェクト全体またはその2つをフォーマットできます。

>>> p1 = {'latitude':41.123,'longitude':71.091}
>>> p2 = {'latitude':56.456,'longitude':23.456}
>>> '{0[latitude]} {0[longitude]} - {1[latitude]} {1[longitude]}'.format(p1, p2)
'41.123 71.091 - 56.456 23.456'

3.6からは、補間された文字列も使用できます。

>>> f'lat:{p1["latitude"]} lng:{p1["longitude"]}'
'lat:41.123 lng:71.091'

ネストされた引用符内で他の引用文字を使用することを覚えておく必要があるだけです。このアプローチのもう1つの利点は、フォーマットメソッドを呼び出すよりもはるかに高速であることです


いいformatですね、それ以上にパフォーマンスの改善はありますか?(
ディクショナリに

2
@BhargavRaoそれほど多くない、2%:D
Antti Haapala

@BhargavRaoあなたがパフォーマンスを探しているなら、これを使ってください'%(latitude)s %(longitude)s'%geopoint;)
Tcll


6

Python 2構文はPython 3でも機能します。

>>> class MyClass:
...     def __init__(self):
...         self.title = 'Title'
... 
>>> a = MyClass()
>>> print('The title is %(title)s' % a.__dict__)
The title is Title
>>> 
>>> path = '/path/to/a/file'
>>> print('You put your file here: %(path)s' % locals())
You put your file here: /path/to/a/file

それに加えてもnoticablyよりパフォーマンスよりますf"""".format();)
Tcll

2
geopoint = {'latitude':41.123,'longitude':71.091}

# working examples.
print(f'{geopoint["latitude"]} {geopoint["longitude"]}') # from above answer
print('{geopoint[latitude]} {geopoint[longitude]}'.format(geopoint=geopoint)) # alternate for format method  (including dict name in string).
print('%(latitude)s %(longitude)s'%geopoint) # thanks @tcll

1
あなたは1つを逃した;)print('%(latitude)s %(longitude)s'%geopoint)これは他の2よりもかなり速い
Tcll

@tcll実際には、文字列内で辞書名を使用できる例が必要でした。このようなもの'%(geopoint["latitude"])s %(geopoint["longitude"])s'%{"geopoint":geopoint}
シェイクアブドゥルワヒド

1

ほとんどの回答は、dictの値のみをフォーマットしました。

キーも文字列にフォーマットしたい場合は、dict.items()を使用できます:

geopoint = {'latitude':41.123,'longitude':71.091}
print("{} {}".format(*geopoint.items()))

出力:

( '緯度'、41.123)( '経度'、71.091)

任意の方法でフォーマットする場合、つまりタプルのようなKey-Valueを表示しない場合:

from functools import reduce
print("{} is {} and {} is {}".format(*reduce((lambda x, y: x + y), [list(item) for item in geopoint.items()])))

出力:

緯度は41.123、経度は71.091です。


「経度」が「緯度」の前に来る可能性があることに注意してくださいgeopoint.items();)
Tcll
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.