在Python中反转C风格格式字符串(`%`)

1 投票
1 回答
1074 浏览
提问于 2025-04-28 00:02

介绍和设置

假设我有一个“模板”字符串,格式如下:

>>> template = """My %(pet)s ate my %(object)s.
... This is a float: %(number)0.2f.
... %(integer)10d is an integer on a newline."""

有了这个模板,我可以生成一个新的字符串,方法是:

>>> d = dict(pet='dog', object='homework', number=7.7375487, integer=743898,)

>>> out_string = template % d

>>> print(out_string)
My dog ate my homework.
This is a float: 7.74.
    743898 is an integer on a newline.

真不错!

问题

我想把 template 应用到 out_string 上,生成一个新的 dict。大概是这样的:

>>> d_approx_copy = reverse_cstyle_template(out_string, template)
>>> print(d_approx_copy)
{pet='dog', object='homework', number=7.74, integer=743898,}

有没有什么简单的 Python 方法可以做到这一点?已经有现成的实现吗?**

备注

*: 我没有使用 模板,因为据我所知,它们目前不支持 反向操作

**: 我知道在 number 的精度损失方面存在一些 风险(比如从 7.7375487 变成 7.74)。我可以处理这个问题。我只是想找一个简单的方法来实现。

暂无标签

1 个回答

3

在我开发这个问题的时候,我发现没有现成的工具可以这样反转C风格的字符串。也就是说,我认为这个问题的答案是:我想要的 reverse_cstyle_template 函数现在并不存在。

在研究这个主题的过程中,我发现了很多类似的问题和答案,它们使用了正则表达式(例如 123)。不过,我想要的是更简单的方式,而且我不想在格式化和解析时使用不同的模板字符串。

这最终让我找到了格式字符串语法,以及Richard Jonesparse包。例如,上面的模板可以用格式字符串语法写成:

>>> template = """My {pet} ate my {object}.
... This is a float: {number:0.2f}.
... {integer:10d} is an integer on a newline."""

有了这个模板,可以使用内置的str.format根据d创建一个新字符串,

template.format(**d)

然后使用parse包来获取d_approx_copy

>>> from parse import parse
>>> d_approx_copy = parse(template, out_string).named

这里需要注意的是,我访问了.named属性。这是因为parse返回一个Result对象(在parse中定义),它捕获了命名固定格式说明符。例如,如果使用,

>>> template = """My {pet} {}ate my {object}.
... This is a float: {number:0.2f}.
... {integer:10d} is an integer on a newline.
... Here is another 'fixed' input: {}"""

>>> out_string = template.format('spot ', 7, **d)

>>> print(out_string)
My dog spot ate my homework.
This is a float: 7.74.
    743898 is an integer on a newline.
Here is another 'fixed' input: 7

那么我们可以通过以下方式获取固定和命名的数据,

>>> data = parse.parse(template, out_string)

>>> print(data.named)
{'pet': 'dog', 'integer': 743898, 'object': 'homework', 'number': 7.74}

>>> print(data.fixed)
('spot ', '7')

很酷吧?

希望有一天这个功能能作为内置功能加入到str或者模板中。不过现在,parse对我来说效果很好。

最后,我觉得有必要再次强调一下在这些步骤中指定精度时会出现的精度损失(也就是说7.7375487变成了7.74)!一般来说,使用精度说明符可能不是个好主意,除非是在创建“可读”的字符串(例如用于“摘要”文件输出),这些字符串不打算进一步处理(也就是说不会被解析)。当然,这与这个问答的重点相悖,但还是需要提到。

撰写回答