Python文字列のformat()
を使用して迅速でダーティなテンプレートとして機能させたいのですが、使用したいdict
には、は整数の(文字列表現)です。簡単な例を次に示します。
s = 'hello there {5}'
d = {'5': 'you'}
s.format(**d)
上記のコードは次のエラーをスローします。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: Tuple index out of range
上記を行うことは可能ですか?
私たちはそれが機能しないことを確立しましたが、解決策はどうですか:
str.format
この場合は機能しません。おかしなことに古い%
フォーマットします。これはお勧めできませんが、迅速かつダーティーなテンプレートを要求しました。
>>> 'hello there %(5)s' % {'5': 'you'}
'hello there you'
ただし、これは整数キーでは機能しないことに注意してください。
>>> 'hello there %(5)s' % {5: 'you'}
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
'hello there %(5)s' % {5: 'you'}
KeyError: '5'
Formatterを拡張して、任意のフィールド名(整数、コロン付きのフィールド名など)を許可するというアイデアが気に入っています。実装は次のようになります。
import string, re
class QuFormatter(string.Formatter):
def _quote(self, m):
if not hasattr(self, 'quoted'):
self.quoted = {}
key = '__q__' + str(len(self.quoted))
self.quoted[key] = m.group(2)
return '{' + m.group(1) + key + m.group(3) + '}'
def parse(self, format_string):
return string.Formatter.parse(self,
re.sub(r'{([^}`]*)`([^}`]*)`([^}]*)}', self._quote, format_string))
def get_value(self, key, args, kwargs):
if key.startswith('__q__'):
key = self.quoted[key]
return string.Formatter.get_value(self, key, args, kwargs)
使用法:
d = {'5': 'you', '6': 'me', "okay":1, "weird:thing!": 123456}
print QuFormatter().format(
'hello there {`5`} {`6`:20s}--{okay}--{`weird:thing!`:20,d}',
**d)
そのため、バックティックのフィールドは文字どおりに扱われます。
からPEP 3101
組み込みの文字列クラス(および2.6のユニコードクラス)は、任意の数の位置引数とキーワード引数を取る新しいメソッド 'format'を取得します。
"The story of {0}, {1}, and {c}".format(a, b, c=d)
フォーマット文字列内では、各位置引数はゼロから始まる番号で識別されるため、上記の例では、「a」は引数0、「b」は引数1です。各キーワード引数はキーワード名で識別されるため、上記の例では、「c」を使用して3番目の引数を参照しています。
str.format
で使用される数値は、位置引数です。だからあなたはそれをすることはできません。
here からPEP 3101に到達できます。関連セクションはStringメソッドの下にあります
@Volatilityが述べたように、これには%
フォーマッターを使用できます。
カスタムget_value
のstring.Formatter
を使用して、インデックスを引数キーにフォールバックする前に、置換キーフィールドを辞書キーとして試すことができます-ここで優先順位と意図の競合の可能性に注意してください...推奨されますが、可能なことのアイデア:
import string
class MyFormatter(string.Formatter):
def get_value(self, key, args, kwargs):
try:
return kwargs[str(key)]
except KeyError:
return super(MyFormatter, self).get_value(key, args, kwargs)
s = 'hello there {5} - you are number {0}'
d = {'5': 'you'}
print MyFormatter().format(s, 1, 2, 3, **d)
# hello there you - you are number 1
実際には、{k}
が(k+1)
番目の位置引数を探すという事実を使用して可能です。
def populate_list(d):
""" Return a list l verifying l[k] = d[str(k)] for each natural k """
return [d.get(str(k)) for k in range(1 + max(map(int, d)))] if d else []
def format_with_int_keys(s,d):
""" Replace each {k} in s by d[str(k)] """
return s.format(*populate_list(d))
s = 'hello there {5}'
d = {'5': 'you'}
print (format_with_int_keys(s,d))
編集:これは実際には@wimソリューションの詳細なバージョンです。