如何推迟/推迟 f 弦的评估? [英] How to postpone/defer the evaluation of f-strings?

查看:24
本文介绍了如何推迟/推迟 f 弦的评估?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用模板字符串来生成一些文件,我喜欢为此目的的新 f 字符串的简洁性,以减少我以前的模板代码:

I am using template strings to generate some files and I love the conciseness of the new f-strings for this purpose, for reducing my previous template code from something like this:

template_a = "The current name is {name}"
names = ["foo", "bar"]
for name in names:
    print (template_a.format(**locals()))

现在我可以这样做了,直接替换变量:

Now I can do this, directly replacing variables:

names = ["foo", "bar"]
for name in names:
    print (f"The current name is {name}")

然而,有时在其他地方定义模板是有意义的——在代码的更高位置,或者从文件导入或其他东西.这意味着模板是一个带有格式化标签的静态字符串.字符串必须发生一些事情才能告诉解释器将字符串解释为新的 f 字符串,但我不知道是否有这样的事情.

However, sometimes it makes sense to have the template defined elsewhere — higher up in the code, or imported from a file or something. This means the template is a static string with formatting tags in it. Something would have to happen to the string to tell the interpreter to interpret the string as a new f-string, but I don't know if there is such a thing.

有没有办法引入一个字符串并将其解释为 f 字符串以避免使用 .format(**locals()) 调用?

Is there any way to bring in a string and have it interpreted as an f-string to avoid using the .format(**locals()) call?

理想情况下,我希望能够像这样编码...(其中 magic_fstring_function 是我不理解的部分):

Ideally I want to be able to code like this... (where magic_fstring_function is where the part I don't understand comes in):

template_a = f"The current name is {name}"
# OR [Ideal2] template_a = magic_fstring_function(open('template.txt').read())
names = ["foo", "bar"]
for name in names:
    print (template_a)

...使用所需的输出(无需读取文件两次):

...with this desired output (without reading the file twice):

The current name is foo
The current name is bar

...但我得到的实际输出是:

...but the actual output I get is:

The current name is {name}
The current name is {name}

推荐答案

这是一个完整的理想 2".

Here's a complete "Ideal 2".

它不是一个 f 字符串——它甚至不使用 f 字符串——但它按要求使用.完全按照指定的语法.没有安全问题,因为我们没有使用 eval().

It's not an f-string—it doesn't even use f-strings—but it does as requested. Syntax exactly as specified. No security headaches since we are not using eval().

它使用一个小类并实现了由print自动调用的__str__.为了摆脱类的有限范围,我们使用 inspect 模块向上跳一帧并查看调用者可以访问的变量.

It uses a little class and implements __str__ which is automatically called by print. To escape the limited scope of the class we use the inspect module to hop one frame up and see the variables the caller has access to.

import inspect

class magic_fstring_function:
    def __init__(self, payload):
        self.payload = payload
    def __str__(self):
        vars = inspect.currentframe().f_back.f_globals.copy()
        vars.update(inspect.currentframe().f_back.f_locals)
        return self.payload.format(**vars)

template = "The current name is {name}"

template_a = magic_fstring_function(template)

# use it inside a function to demonstrate it gets the scoping right
def new_scope():
    names = ["foo", "bar"]
    for name in names:
        print(template_a)

new_scope()
# The current name is foo
# The current name is bar

这篇关于如何推迟/推迟 f 弦的评估?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆