是否有可调用的等效于f字符串语法?

Dav*_*Eyk 6 python string templates

每个人都喜欢Python 3.6的新f字符串:

In [33]: foo = {'blah': 'bang'}

In [34]: bar = 'blah'

In [35]: f'{foo[bar]}'
Out[35]: 'bang'
Run Code Online (Sandbox Code Playgroud)

但是,尽管它们在功能上非常相似,但它们的语义并不完全相同str.format()

In [36]: '{foo[bar]}'.format(**locals())
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-36-b7ef5aead76c> in <module>()
----> 1 '{foo[bar]}'.format(**locals())

KeyError: 'bar'
Run Code Online (Sandbox Code Playgroud)

特别是,str.format()处理getitem语法有很大不同

In [39]: '{foo[blah]}'.format(**locals())
Out[39]: 'bang'
Run Code Online (Sandbox Code Playgroud)

鉴于能够处理成熟的python表达式语法,f字符串很棒,我喜欢它们。但是它们有一个障碍:它们会立即得到评估,而str.format()我可以将字符串以其格式保存为模板,并在不同的上下文中对其进行多次格式化。

那么,是否存在等效的方法将字符串另存为模板,并在以后使用f字符串语义对其进行求值?除了定义功能之外?str.format()f琴弦有等同于f弦的琴弦吗?

更新:

因此,这里假设接口为例:

In [40]: mystr = '{foo[bar]}'

In [41]: make_mine_fstring(mystr, foo=foo, bar=bar)
Out[41]: 'bang'
Run Code Online (Sandbox Code Playgroud)

Ser*_*yev 4

简短回答:不。

您可以阅读有关这些 f 字符串的PEP-498 。它清楚地定义了它们的目的和概念:这些字符串就地求值。结果是通常的str格式化内容。您无法将 f 字符串存储为模板,因为 f 字符串没有特殊的对象。

PEP-498 的“ f-string 和 str.format 表达式之间的差异”部分中也提到了您的具体示例。

因此,无论您做什么,您要么使用内联就地 f 字符串,要么使用s.format()具有不同行为的旧语法。

如果你想从文件中读取 f 字符串并根据 f 字符串的语法对其求值,可以使用 eval:

foo = {'blah': 'bang', 'bar': 'sorry'}
bar = 'blah'

tpl = '{foo[bar]}'
print(tpl)

print(tpl.format(**locals()))  # sorry
print(eval(f'f{tpl!r}'))  # bang
Run Code Online (Sandbox Code Playgroud)

请注意我们如何首先使用 f 字符串,但将其转换tpl为它自己的repr以立即进行评估。通常,对于简单类型,eval(repr(val))应该返回val。但我们不只是输入repr(tpl)(or {tpl!r}),而是将常规字符串的repr转换为 f 字符串,然后对其求值。