带有带有整数键的dict的python字符串格式()[重复]

Posted

技术标签:

【中文标题】带有带有整数键的dict的python字符串格式()[重复]【英文标题】:python string format() with dict with integer keys [duplicate] 【发布时间】:2014-01-07 18:47:54 【问题描述】:

我想使用 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 作为变量名,因为它会覆盖内置的str 类。 如果密钥实际上是整数,[5] 会起作用。 【参考方案1】:

这实际上是可能的,使用事实k 寻找(k+1)th 位置参数。

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 解决方案的详细版本。

【讨论】:

【参考方案2】:

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

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

【讨论】:

【参考方案3】:

您可以在自定义 string.Formatter 中使用 get_value 执行某些操作,以尝试将替换字段作为字典键,然后再将索引返回到 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

【讨论】:

【参考方案4】:

来自 PEP 3101

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

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

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

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

您可以通过here 联系 PEP 3101。相关部分在 String Methods

正如@Volatility 提到的,您可以为此使用% 格式化程序。

【讨论】:

【参考方案5】:

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

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

【讨论】:

【参考方案6】:

请参阅this post 以获取问题的答案。您似乎不能使用由数字组成的字符串作为格式字符串中的字典键(docs link)。

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

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

【讨论】:

链接答案中最重要的部分是来自文档的引用:Because arg_name is not quote-delimited, it is not possible to specify arbitrary dictionary keys (e.g., the strings '10' or ':-]') within a format string.

以上是关于带有带有整数键的dict的python字符串格式()[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何将带有元组键的 python 字典转换为 pandas 多索引数据框?

带有字符串键的矩阵是不是有 Boost(或其他常见库)类型?

Rails 无法正确解码来自 jQuery 的 JSON(数组变成带有整数键的散列)

带有向量作为键的 STL 映射

python用两个键将带有行和列标题的csv文件读入字典

使用带有 python/pandas 的 dict 理解与 str.contains 进行部分字符串匹配