在变量中的python字符串上触发f字符串解析

时间:2019-04-01 14:30:11

标签: python python-3.x string string-formatting f-string

此问题来自处理jupyter magics,但可以用更简单的方式表达。给定一个字符串s = "the key is {d['key']}"和一个字典d = {'key': 'val'},我们想解析该字符串。

旧方法为.format(),这将引发错误-它不处理字典键。

"the key is {d['key']}".format(d=d)  # ERROR

我认为唯一的解决方法是将字典转换为对象(解释为here或此处)。

"the key is {d.key}".format(obj(d))

但是Martijn很好地解释了,您可以简单地删除引号使它起作用:

"the key is {d[key]}".format(d=d)

仍然,新方法f'string'确实以直观的python方式处理字典键:

f"the key is {d['key']}"

它还处理函数-.format也无法处理。

f"this means {d['key'].lower()}"

尽管我们现在知道您可以使用.format做到这一点,但我仍然想知道原来的问题:给定sd,怎么办您是否强制f'string'进行s解析?我添加了另一个带有大括号内的函数的示例,该示例.format也无法处理,f'string'可以解决。

是否有可用的功能.fstring()或方法? Python在内部使用什么?

2 个答案:

答案 0 :(得分:4)

字符串格式可以处理大多数字符串字典键很好,但您需要删除引号:

"the key is {d[key]}".format(d=d)

演示:

>>> d = {'key': 'val'}
>>> "the key is {d[key]}".format(d=d)
'the key is val'

str.format()语法与Python表达式语法(f字符串最支持的语法)不太一样。

来自Format String Syntax documentation

field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
[...]
element_index     ::=  digit+ | index_string
index_string      ::=  <any source character except "]"> +

  

[A] n形式为'[index]'的表达式使用__getitem__()进行索引查找

语法是有限的,因为它将所有仅数字的字符串转换为整数,并且其他所有内容始终被解释为字符串(尽管您可以使用嵌套的{}占位符从中动态插入键值)另一个变量)。

如果您必须支持任意表达式,就像f字符串一样,并且不要从不受信任的来源获取模板字符串(这部分很重要),那么您可以先parse out the field name components,然后使用eval() function评估值,然后再输出最终字符串:

from string import Formatter

_conversions = {'a': ascii, 'r': repr, 's': str}

def evaluate_template_expressions(template, globals_=None):
    if globals_ is None:
        globals_ = globals()
    result = []
    parts = Formatter().parse(template)
    for literal_text, field_name, format_spec, conversion in parts:
        if literal_text:
            result.append(literal_text)
        if not field_name:
            continue
        value = eval(field_name, globals_)
        if conversion:
            value = _conversions[conversion](value)
        if format_spec:
            value = format(value, format_spec)
        result.append(value)
    return ''.join(result)

现在接受报价:

>>> s = "the key is {d['key']}"
>>> d = {'key': 'val'}
>>> evaluate_template_expressions(s)
'the key is val'

从本质上讲,您可以使用eval(f'f{s!r}', globals())进行相同的操作,但是以上内容可能使您对想要支持的表达式有了更多的控制。

答案 1 :(得分:0)

  

[G]给出sd,您如何强制f'string'的{​​{1}}解析?有可用的功能或方法吗?

这可以使用s完成。 But beware eval!

eval

>>> eval('f' + repr(s)) the key is val 用来转义任何引号,并用引号将repr自身包裹起来。

如果您知道要格式化的变量(在这种情况下为s),请选择Martijn's answer进行d。由于str.format的危险,上述解决方案应该是您的最后选择。