如何枚举字符串占位符?

时间:2016-09-02 10:38:58

标签: python string

我想知道从字符串中枚举占位符的最佳方法是什么,我已经看到已经有另一篇文章询问how-can-i-find-all-placeholders-for-str-format-in-a-python-string-using-a-regex但是我不确定提供的答案是否正确地给了我什么我正在寻找,让我们来看看这个小小的测试:

import string

tests = [
    ['this is my placeholder 1 {} and this is the 2 {}', 2],
    ['another placeholder here {} and here \"{}\"', 2]
]
for s in tests:
    num_placeholders = len([
        name for text, name, spec, conv in string.Formatter().parse(s[0])])
    if num_placeholders != s[1]:
        print("FAIL: {0} has {1} placeholders!!! excepted result {2}".format(
            s[0], num_placeholders, s[1]))

似乎string.Formatter没有给我正在寻找的预期答案:

FAIL: another placeholder here {} and here "{}" has 3 placeholders!!! excepted result 2

2 个答案:

答案 0 :(得分:2)

因为你忽略了parse(s)返回的元组上的其他元素:

>>> import string
>>> 
>>> tests = [
...     "{} spam eggs {}",
...     "{0} spam eggs {1}",
...     "{0:0.2f} spam eggs {1:0.2f}",
...     ">>> list(string.Formatter().parse('{}'))
[('', '', '', None)]
 spam eggs {{2}}"
... ]
>>> for s in tests:
...     print [x for x in string.Formatter().parse(s)]
... 
[('', '', '', None), (' spam eggs ', '', '', None)]
[('', '0', '', None), (' spam eggs ', '1', '', None)]
[('', '0', '0.2f', None), (' spam eggs ', '1', '0.2f', None)]
[('{', None, None, None), ('1}', None, None, None), (' spam eggs {', None, None, None), ('2}', None, None, None)]

编辑:我明白你的意思了。是的,解析的解释不直观也不明显。返回列表的长度不是占位符的数量,而是字符串的文字部分的计数,包括开头的空字符串,但不包括结尾的空字符串。每个元素还包含以下格式。例如:

>>> list(string.Formatter().parse('a {}'))
[('a ', '', '', None)]

这是基本情况,并且只有一个空字符串的文字文本。实际上有两个空字符串,但解析器不包含最后一个空字符串。

>>> list(string.Formatter().parse('{} b'))
[('', '', '', None), (' b', None, None, None)]

现在我们和以前一样:只有一个文字字符串" a"没有任何内容。由于格式括号后面没有任何内容,因此没有元素。

>>> list(string.Formatter().parse('a {1} b {2} c'))
[('a ', '1', '', None), (' b ', '2', '', None), (' c', None, None, None)]

这是一个有趣的案例:因为格式括号位于开头,所以第一个文字字符串是一个空的文字字符串,并且跟在字符串" B&#34 ;.

['a ', ' b ', ' c']

这是一个非常完整的例子。我们有三个文字字符串:>>> [x[0] for x in string.Formatter().parse('another placeholder here {} and here \"{}\"')] ['another placeholder here ', ' and here "', '"'] 。令人困惑的部分是格式括号{}的特定格式信息与前一个文字字符串元素合并。

EDIT2:

>>> [x[0] for x in string.Formatter().parse('another placeholder here {} and here qqq{}www')]
['another placeholder here ', ' and here qqq', 'www']

我们遵循相同的逻辑。引号只是原始的文字字符串,我们可以将引号更改为其他内容:

>>> [x for x in string.Formatter().parse('a{}')]
[('a', '', '', None)]
>>> [x for x in string.Formatter().parse('a')]
[('a', None, None, None)]

如果您只考虑'名称'从每个返回的元组,你只得到文字字符串。在每个单独的元素之间是格式占位符。

您需要从格式化字符串的角度理解parse()的结果。此结果使得生成输出格式化字符串变得简单。例如:

>>> def count_placeholders(fmt):
...     count = 0
...     L = string.Formatter().parse(fmt)
...     for x in L:
...         if x[1] is not None:
...             count += 1
...     return count
... 
>>> count_placeholders('')
0
>>> count_placeholders('{}')
1
>>> count_placeholders('{}{}')
2
>>> count_placeholders('a {}{}')
2
>>> count_placeholders('a {} b {}')
2
>>> count_placeholders('a {} b {} c')
2

使用此逻辑,您可以计算格式字符串中占位符的数量,如下所示:

echo

答案 1 :(得分:0)

import string

def count_placeholders(fmt):
    return sum(1 for x in string.Formatter().parse(fmt) if x[1] is not None)