python string format() with dict with integer keys

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20677660/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 21:00:35  来源:igfitidea点击:

python string format() with dict with integer keys

pythonstringtemplatesdictionaryformat

提问by yee379

I would like to use Python string's format()to act as a quick and dirty template. However, the dictthat I would like to use has keys which are (string representations) of integers. a simplified example follows:

我想使用 Python 字符串format()作为一个快速而肮脏的模板。但是,dict我想使用的键是整数(字符串表示)。一个简化的例子如下:

s = 'hello there {5}'
d = {'5': 'you'}
s.format(**d)

the above code throws the following error:

上面的代码抛出以下错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: tuple index out of range

is it possible to do the above?

是否可以执行上述操作?

采纳答案by Volatility

We've established that it won't work, but how about a solution:

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

Although str.formatwon't work in this case, funnily enough the old %formatting will. This is not recommended, but you did ask for a quick and dirty template.

虽然str.format在这种情况下不起作用,但有趣的是旧%格式会起作用。不推荐这样做,但您确实要求提供一个快速而肮脏的模板

>>> 'hello there %(5)s' % {'5': 'you'}
'hello there you'

Do note though that this won't work for integer keys.

请注意,这不适用于整数键。

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

回答by Ffisegydd

See this postfor answers to your problems. It seems that you cannot use strings consisting of numbers as dictionary keys in format strings (docs link).

请参阅此帖子以了解您的问题的答案。似乎您不能使用由数字组成的字符串作为格式字符串中的字典键(文档链接)。

If you can use a key other than 5 then it will work:

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

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

回答by FallenAngel

From PEP 3101

来自PEP 3101

The built-in string class (and also the unicode class in 2.6) will gain a new method, 'format', which takes an arbitrary number of positional and keyword arguments:

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

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

Within a format string, each positional argument is identified with a number, starting from zero, so in the above example, 'a' is argument 0 and 'b' is argument 1. Each keyword argument is identified by its keyword name, so in the above example, 'c' is used to refer to the third argument.

在格式字符串中,每个位置参数都用一个数字标识,从零开始,因此在上面的示例中,“a”是参数 0,“b”是参数 1。每个关键字参数由其关键字名称标识,因此在上面的例子中,'c' 用来指代第三个参数。

Numeric values used in str.formatare positional arguments. So you can not do that.

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

You can reach PEP 3101 from here. Related section is is under String Methods

你可以从这里到达 PEP 3101 。相关部分是在字符串方法下

As @Volatility mentioned, you can use %formatter for this.

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

回答by Jon Clements

You could do something with get_valuein a custom string.Formatterto try replacement fields as dictionary keys before falling back on index into arg keys - note the possible conflict of priority and intent here... so it's not exactly recommended, but an idea of what's possible:

您可以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

回答by georg

I love the idea of extending the Formatter so that it allows arbitrary field names (integers, field names with a colon etc). An implementation might look like this:

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

Usage:

用法:

d = {'5': 'you', '6': 'me', "okay":1, "weird:thing!": 123456}
print QuFormatter().format(
     'hello there {`5`} {`6`:20s}--{okay}--{`weird:thing!`:20,d}', 
     **d)

So fields in backticks are treated literally.

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

回答by YvesgereY

It is actually possible, using the fact {k}seeks for the (k+1)th positional argument.

它实际上是可能的,使用事实{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))

Edit: It's actually a detailed version of @wim solution.

编辑:它实际上是@wim 解决方案的详细版本。