如何将字符串转换为f-string

piR*_*red 21 python python-3.6 f-string

我正在阅读关于python的新f字符串的博客,它们看起来非常整洁.但是,我希望能够从字符串或文件加载f-string.

我似乎找不到任何字符串方法或其他功能.

从上面链接中的示例:

name = 'Fred'
age = 42
f"My name is {name} and I am {age} years old"

'My name is Fred and I am 42 years old'
Run Code Online (Sandbox Code Playgroud)

但是,如果我有一个字符串s怎么办?我希望能够有效s,这样的事情:

name = 'Fred'
age = 42
s = "My name is {name} and I am {age} years old"
effify(s)
Run Code Online (Sandbox Code Playgroud)

事实证明,我已经可以执行类似的操作str.format并获得性能提升.即:

format = lambda name, age: f"My name is {name} and I am {age} years old"
format('Ted', 12)

'My name is Ted and I am 12 years old'
Run Code Online (Sandbox Code Playgroud)

use*_*ica 16

f-strings是代码.不只是在安全中,"当然是字符串文字是代码"的方式,而是以危险的,任意代码执行的方式.这是一个有效的f字符串:

f"{__import__('os').system('install ransomware or something')}"
Run Code Online (Sandbox Code Playgroud)

并且在评估时它将执行任意shell命令.

你问的是如何从文本文件中加载一个字符串并将其作为代码进行评估,答案归结为eval.这当然是一个安全风险,可能是一个坏主意,所以我建议不要尝试从文件加载f-strings.

如果f"My name is {name} and I am {age} years old"要从文件加载f-string ,则实际放入

f"My name is {name} and I am {age} years old"
Run Code Online (Sandbox Code Playgroud)

在文件中,f引号和所有.

从文件中读取它,编译并保存(因此eval不必每次都重新编译它):

compiled_fstring = compile(fstring_from_file, '<fstring_from_file>', 'eval')
Run Code Online (Sandbox Code Playgroud)

并评估它eval:

formatted_output = eval(compiled_fstring)
Run Code Online (Sandbox Code Playgroud)

如果你这样做,要非常小心你加载你的f字符串的来源.

  • 我不太明白为什么有人会使用compile和eval而不是`string_from_file.format(**locals())`.如果答案是"因为f-strings可以有更复杂的表达式",那么编写处理所有必需表达式的小型DSL似乎比使用eval并允许任意代码执行更可取. (3认同)
  • @stevepastelan 基本上我推荐使用 `str.format` 方法而不是 f 字符串。对于像这个答案中这样的 f 字符串, `myStr=f"my name is {name} and I'm {age} years old"`,您只需删除前导的 `f` 并使用 `myString.format(name= &lt;namevalue&gt;,age=&lt;agevalue&gt;)` 获取格式化输出。如果您想从作用域获取占位符值而不是单独传递它们,请使用 myStr.format(**locals()) 将所有本地变量传递给 format。当然,这不适用于 f 字符串中的表达式(例如 `{age+1}`),因此如果需要它们,您必须自己处理它们...... (2认同)

Jar*_*rno 8

一个简单的解决方案是使用f字符串和eval。

def effify(non_f_str: str):
    return eval(f'f"""{non_f_str}"""')

name = 'Fred'
age = 42
s = "My name is {name} and I am {age} years old"
effify(s)
'My name is Fred and I am 42 years old'
Run Code Online (Sandbox Code Playgroud)

基本上,这会在字符串前加上“ f”,然后作为代码求值。三重引号也有助于容纳多行字符串。该函数将尝试从调用周围的作用域中提取f字符串中引用的变量。如前所述,使用eval可能有潜在的危险,但是如果您知道您的来源,那么我认为这并不比执行任何其他代码更危险。

  • 我真诚地希望没有人用不受信任的输入来做这件事:P (3认同)
  • 非常非常整洁。但当然也很危险。 (2认同)
  • 正如所指出的,这是一个非常糟糕的解决方案,除了简单的“.format”之外,除了“.format”没有的许多问题之外,什么也没有带来。 (2认同)

Chr*_*ean 7

但是,如果我有一个字符串s怎么办?我希望能够对s进行有效处理,例如:

name = 'Fred'
age = 42
s = "My name is {name} and I am {age} years old"
effify(s)
Run Code Online (Sandbox Code Playgroud)

AFAIU,根据PEP 498- 文字字符串插值,这是不可能1。无法以编程方式创建f字符串:

在Python源代码中,f字符串是文字字符串,前缀为'f',其中包含在花括号内的表达式


1 当然,除非您愿意使用exec@coldspeed之类的东西。但是到那时,利弊可能超过利弊。