web-dev-qa-db-ja.com

python string format()dict with integer keys

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

上記を行うことは可能ですか?

17
yee379

私たちはそれが機能しないことを確立しましたが、解決策はどうですか:

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'
28
Volatility

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)

そのため、バックティックのフィールドは文字どおりに扱われます。

8
georg

問題への回答については この投稿 を参照してください。数字からなる文字列は、フォーマット文字列( docs link )の辞書キーとして使用できないようです。

5以外のキーを使用できる場合は、機能します。

my_string='hello there {spam:s}'
d={'spam': 'you'}
print my_string.format(**d) # Returns "hello there you"
7
Ffisegydd

から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が述べたように、これには%フォーマッターを使用できます。

3
FallenAngel

カスタムget_valuestring.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
1
Jon Clements

実際には、{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ソリューションの詳細なバージョンです。

0
YvesgereY