如何使用ast.literal_eval评估f字符串

时间:2017-02-28 00:52:25

标签: python string python-3.6

尝试使用ast.literal_eval评估f字符串时,我得到ValueError关于"格式错误的节点或字符串":

from ast import literal_eval

a = 10

literal_eval("f'test {a}'")

引发以下错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<...> in <module>()
      3 a = 10
      4 
----> 5 literal_eval("f'test {a}'")

C:\...\lib\ast.py in literal_eval(node_or_string)
     83                     return left - right
     84         raise ValueError('malformed node or string: ' + repr(node))
---> 85     return _convert(node_or_string)
     86 
     87 

C:\...\lib\ast.py in _convert(node)
     82                 else:
     83                     return left - right
---> 84         raise ValueError('malformed node or string: ' + repr(node))
     85     return _convert(node_or_string)
     86 

ValueError: malformed node or string: <_ast.JoinedStr object at 0x000001F20CE718D0>

然而,它对原始字符串或二进制字符串没有问题:

>>> literal_eval("r'This'")
'This'
>>> literal_eval("b'This'")
b'This'

我可以让ast.literal_eval处理f字符串吗?如果是的话,我需要改变什么?

2 个答案:

答案 0 :(得分:2)

这是不可能的。 f-string类似于以下 1

map = {}
map.update(globals())
map.update(locals())
string.format(**map)

这实际上是一种戏剧性的轻描淡写 - f-strings还支持其他类型的表达式,这些表达式不仅仅是名称查找,也不支持像vanilla格式字符串可以获得的项目访问等简单事物。例如它们支持任何其他有效的python表达式,包括函数调用,数学方程等。

>>> expr = '"boom"'
>>> f'foo{eval(expr)}'
'fooboom'

使用__format__协议评估f-string,并使用普通python评估它包含的表达式。这意味着f-string 不能为文字。它是 1 的表达式。请注意,与任意表达式一样,它无法安全地进行评估 - 因此您可能甚至不希望它是“可评估的”#34;无论如何,请ast.literal_eval

1 在AST中,您会看到它是通过JoinedStrStrFormattedValue个ast节点完成的。其中,唯一可以被视为文字的是Str

答案 1 :(得分:0)

F字符串可以包含任意复杂的表达式。一个简单的例子。

>>> a = 2; b=3; print(f'x{a**b}x')

x8x

它们既不是文字,也不是文字,也不适合literal_eval。