打印字符串时数字字典键作为占位符?

Numerical dictionary keys as placeholders when printing strings?

我有以下代码:

board_dic = {
    0: '_',
    1: '_',
    2: '_',
    3: '_',
    4: '_',
    5: '_',
    6: '_',
    7: '_',
    8: '_',
}

print("|{0}|{1}|{2}|\n|{3}|{4}|{5}|\n|{6}|{7}|{8}|".format(**board_dic)

运行时的输出为:

line 28, in <module>
    print("|{0}|{1}|{2}|\n|{3}|{4}|{5}|\n|{6}|{7}|{8}|".format(**board_dic))
IndexError: Replacement index 0 out of range for positional args tuple

我找不到解决这个问题的任何地方。如果我将board_dic中的键替换为字符串,如'a''b''c'等,并将打印语句中的占位符替换为[=13] =]、'b''c' 等,那么我的打印语句将毫无问题地执行。但是,问题似乎特别出在数字键字典值上。

为什么会这样,我该如何解决?

当使用format-strings时,像{1}这样的占位符代表“format()”的第n个参数。这与命名 keyword-arguments 不同。使用 **board_dic 会将它们分解为 keyword-arguments。这就是它无法按预期工作的原因。

相反,您需要使用单个 * 来使用位置参数。但是随后您会遇到一个不同的问题:据我所知,字典排序只是 Python 3.7 中语言规范的一部分。它在以前的版本中已经稳定,但这是一个实现细节,在其他版本(pypy、jython 等)中无法保证。

所以我们需要对其进行排序以 100% 确定它有效。

由于键是数字,我们可以简单地对 board_dic.items() 进行排序。这会给我们一个稳定的替代品。

然后我们需要提取有效值。我们可以用一个简单的 list-comprehension.

来做到这一点

更改后我们是 - 只要字典不包含任何缺失的数字 - 100% 确定输出是正确的。

我们可以使用单个“positional-argument-expansion”在 .format() 中使用结果列表。

board_dic = {
    0: '_',
    1: '_',
    2: '_',
    3: '_',
    4: '_',
    5: '_',
    6: '_',
    7: '_',
    8: '_',
}

values = [value for _, value in sorted(board_dic.items())]

print("|{0}|{1}|{2}|\n|{3}|{4}|{5}|\n|{6}|{7}|{8}|".format(*values))

如果您知道要查找的内容,请参阅说明 here:

The field_name itself begins with an arg_name that is either a number or a keyword. If it’s a number, it refers to a positional argument, and if it’s a keyword, it refers to a named keyword argument. If the numerical arg_names in a format string are 0, 1, 2, … in sequence, they can all be omitted (not just some) and the numbers 0, 1, 2, … will be automatically inserted in that order. 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.

简单来说,'{0} {1}'.format(...) 的意思是“将 {0} 替换为第一个位置参数,将 {1} 替换为 format(...) 的第二个位置参数。

位置参数是那些在函数调用中没有指定参数名称而传递的参数。例如在 format(1, 2, c=3) 中,12 是位置参数,而 c=3 是关键字参数。

但是 **board_dic 语法指定了关键字参数! format(**board_dic) 等同于 format(0='_', 1='_', 2='_', ...)1 并且有 no 个位置参数。因此,使用 {0}{1}{2} 等获取第一个、第二个、第三个等位置参数失败。

为了将带有整数键的字典传递给 format,您可以使用:

print("|{d[0]}|{d[1]}|{d[2]}|\n|...".format(d=board_dic))

1不允许将数字作为关键字是另一个问题。

要使用它们的键将 dict 值转换为 str.format 方法的位置参数,您可以将 dict 长度的 range 映射到 get 方法dict 并解压输出序列作为参数:

print("|{0}|{1}|{2}|\n|{3}|{4}|{5}|\n|{6}|{7}|{8}|".format(*map(board_dic.get, range(len(board_dic)))))