首页 > 解决方案 > Python 3.6 'f' 字符串的表达式与 `.format` 或 `.format_map` 不兼容

问题描述

我发现它.format_map与Python 3.6字符串.format不兼容,因为本机前缀允许复杂的表达式(例如切片和函数调用),但 do不允许复杂的表达式,例如:ff.format_map

>>> version = '1.13.8.10'                                                                               

>>> f'example-{".".join(version.split(".")[:3])}'                                                          
'example-1.13.8'

>>> 'example-{".".join(version.split(".")[:3])}'.format_map(dict(version=version))                      
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: '"'

'"'

>>> 'example-{".".join(version.split(".")[:3])}'.format(version=version)                                
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: '"'

'"'

我真的希望能够通过配置文件公开 Python 字符串的全部功能,其中用户提供一个字符串,该字符串可能包含引用同一文件的f非平凡段,并且可以选择执行一些基本数据操作,例如在 YAML 文件中{...}我使用后处理键的子集,.format以便它们可以引用同一配置文件中的变量。

这适用于简单的变量,例如{version}YAML 文件是一个带有version键的字典,我将 dict 作为参数传递给.format_map,但抛出KeyError更复杂的表达式(如上所示)。

必须有一种方法可以获得与f字符串相同的功能......我以为.format_map是......但它不提供复杂的表达式......

标签: python

解决方案


你正在寻找eval

>>> def format_map_eval(string, mapping):
...     return eval(f'f{string!r}', mapping)
...
>>> version = '1.13.8.10'
>>> some_config_string = 'example-{".".join(version.split(".")[:3])}'
>>> format_map_eval(some_config_string, dict(version=version))
'example-1.13.8'

这至少是明确的关于你提供这个。

f-strings 的关键特性是它们在格式化括号内评估任意表达式。如果您想要一个执行此操作的函数调用,那么您需要 eval。

现在我考虑一下,我不确定这在实现中是否安全或可移植,因为据我所知,无法保证reprof 。str


推荐阅读