python string format(),带有带整数键的dict

时间:2013-12-19 09:22:34

标签: python string templates dictionary format

我想使用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

可以做到以上几点吗?

6 个答案:

答案 0 :(得分:27)

我们已经确定它不起作用,但解决方案如何:

虽然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'

答案 1 :(得分:8)

我喜欢扩展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)

所以反叛中的字段按字面意思处理。

答案 2 :(得分:7)

有关问题的解答,请参阅this post。您似乎不能在格式字符串(docs link)中使用由数字组成的字符串作为字典键。

如果您可以使用5以外的密钥,那么它将起作用:

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

答案 3 :(得分:3)

来自 PEP 3101

  

内置的字符串类(以及2.6中的unicode类)将会       获得一种新方法'format',它采用任意数量的方法       位置和关键字参数:

"The story of {0}, {1}, and {c}".format(a, b, c=d)
  

在格式字符串中,标识每个位置参数       一个数字,从零开始,所以在上面的例子中,'a'是       参数0和'b'是参数1.每个关键字参数都是       由关键字名称标识,因此在上面的示例中,'c'是       过去是指第三个论点。

str.format中使用的数字值是位置参数。所以你不能这样做。

您可以从here到达PEP 3101。相关部分位于字符串方法

正如@Volatility所述,您可以使用%格式化程序。

答案 4 :(得分:1)

您可以在自定义get_value中对string.Formatter执行某些操作,以便在将索引转换为arg键之前尝试将替换字段作为字典键 - 请注意此处可能存在的优先级和意图冲突...所以它并不是完全推荐的,而是对可能性的概念:

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

答案 5 :(得分:0)

实际上,使用事实{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解决方案的详细版本。