LoginSignup
1
0

Python フォーマット文字列からプレースホルダ名etcを取得する

Posted at

問題意識

たとえば

greeting = "My name is {name}, inmate number {number:04d}"

のような文字列を考える。greeting.format(name='Shohei', number=17)のようにすれば、nameあるいはnumberというプレースホルダに明示的に値を与えることもできるし、通常の文字列の代わりにf-stringにすればスコープからnamenumberといった名前を引っ張ってきてくれる。

せっかくなのでconfig fileなんかから引っ張ってきた設定も、この方式でフレキシブルにフォーマットできるようにしたい。

もちろん実際に使うときには

cfg = dict(...)

...

text = greeting.format(**cfg)

のようなかたちで使えば良いけれど、実際にformat()メソッドを呼ぶ前にcfgの中に対応したキーが想定された型で入っているかをチェックしたい。

具体的には、たとえば上のgreetingの場合、このフォーマット文字列から

  • nameという変数が必要
  • numberという変数が、整数に変換できる型で必要

という情報を引き出したい。

stringモジュールの利用

そこで使うのは、format()メソッドの内部(関連?)実装であるstringモジュールになる。

string.Formatterクラスがフォーマッティングにかかわる諸々の作業を抽象化してくれている。今回の場合、parseメソッドを使う:

>>> import string
>>> 
>>> greeting = "My name is {name}, inmate number {number:04d}, cheers!"
>>> 
>>> fmter = string.Formatter()
>>> fmter.parse(greeting)
<formatteriterator object at 0x10125b7e0>
>>> for elem in fmter.parse(greeting)
...     print(elem)
...
('My name is ', 'name', '', None)
(', inmate number ', 'number', '04d', None)
(', cheers!', None, None, None)
>>> 

parseメソッドは、4-tupleのイテレータを返す。各tupleは(literal, field, spec, conversion)の形式になっている:

  • literal: プレースホルダの前にあるリテラル文字列
  • field: プレースホルダに指定された名前
  • spec: フォーマット形式
  • conversion: (現段階では、どういうときに出てくるかちょっとよくわからなかった)

その他参考

  • PEP 3101 意外と知らないことがあった
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0