如何将 f 字符串与变量一起使用,而不是与字符串文字一起使用?

问题描述 投票:0回答:5

我想将 f-string 与我的字符串变量一起使用,而不是使用字符串文字定义的字符串,

"..."

这是我的代码:

name=["deep","mahesh","nirbhay"]
user_input = r"certi_{element}" # this string I ask from user  

for element in name:
    print(f"{user_input}")

此代码给出输出:

certi_{element}
certi_{element}
certi_{element}

但我想要:

certi_{deep}
certi_{mahesh}
certi_{nirbhay}

我该怎么做?


另请参阅:如何推迟/延迟 f 字符串的评估?

python string-formatting string-interpolation f-string
5个回答
83
投票
将表达式结果插入到

literal

 中时,
f"..." 字符串非常有用,但是您没有文字,而是在单独的变量中拥有模板字符串。

您可以使用

str.format()
将值应用于该模板:

name=["deep","mahesh","nirbhay"]
user_input = "certi_{element}" # this string i ask from user  

for value in name:
    print(user_input.format(element=value))

使用名称的字符串格式化占位符(例如

{element}
)不是变量。您可以在
str.format()
调用的关键字参数中为每个名称分配一个值。在上面的示例中,
element=value
传入
value
变量的值,以用
element
填充占位符。

f
字符串不同,
{...}
占位符是 not 表达式,您不能在模板中使用任意 Python 表达式。这是一件好事,您不会希望最终用户能够在您的程序中执行任意 Python 代码。有关详细信息,请参阅格式字符串语法文档

您可以传入任意数量的名字;字符串模板无法使用其中任何一个。如果将 str.format()

**mapping
调用约定结合起来,您可以使用任何字典作为值的来源:

template_values = { 'name': 'Ford Prefect', 'number': 42, 'company': 'Sirius Cybernetics Corporation', 'element': 'Improbability Drive', } print(user_input.format(**template_values)

上面的内容将允许用户在其模板中使用 
template_values

中的任何名称,任意次数。


虽然您可以使用

locals()

globals()
生成将变量名称映射到值的字典,但我不推荐这种方法。使用如上所述的专用命名空间来限制可用的名称,并为最终用户记录这些名称。
    


50
投票

def fstr(template): return eval(f"f'{template}'")

然后你可以这样做:

name=["deep","mahesh","nirbhay"] user_input = r"certi_{element}" # this string i ask from user for element in name: print(fstr(user_input))

输出:

certi_deep certi_mahesh certi_nirbhay

但请注意,用户可以在模板中使用表达式,例如:

import os # assume you have used os somewhere user_input = r"certi_{os.environ}" for element in name: print(fstr(user_input))

你绝对不想要这个!

因此,一个更安全的选择是定义:

def fstr(template, **kwargs): return eval(f"f'{template}'", kwargs)

不再可能使用任意代码,但用户仍然可以使用字符串表达式,例如:

user_input = r"certi_{element.upper()*2}" for element in name: print(fstr(user_input, element=element))

给出输出:

certi_DEEPDEEP certi_MAHESHMAHESH certi_NIRBHAYNIRBHAY

这在某些情况下可能是需要的。


3
投票

format

 方法来动态插值,而不是使用 f 字符串,语法非常相似。
如果您希望用户只能访问少量特定变量,您可以执行类似的操作

name=["deep", "mahesh", "nirbhay"] user_input = "certi_{element}" # this string i ask from user for element in name: my_str = user_input.format(element=element) print(f"{my_str}")

您当然可以重命名用户输入的键与您使用的变量名称:

my_str = user_input.format(element=some_other_variable)

您可以让用户访问您的整个命名空间(或至少是其中的大部分)。请不要这样做,但请注意您可以:

my_str = user_input.format(**locals(), **globals())

我使用 
print(f'{my_str}')

而不是

print(my_str)
的原因是为了避免出现文字大括号被视为进一步错误扩展的情况。例如,
user_input = 'certi_{{{element}}}'
    


1
投票
https://stackoverflow.com/a/54780825/7381826

利用这个想法,我调整了你的代码:

user_input = r"certi_" for element in name: print(f"{user_input}{element}")

我得到了这个结果:

certi_deep certi_mahesh certi_nirbhay

如果您宁愿坚持问题中的布局,那么最后的编辑就可以解决问题:

for element in name: print(f"{user_input}" "{" f"{element}" "}")

阅读所有其他问题的安全问题,我认为这种替代方案没有严重的安全风险,因为它没有使用 eval() 定义新函数。

我不是安全专家,如果我错了,请纠正我。


0
投票

name=["deep","mahesh","nirbhay"] user_input = "certi_{element}" # this string I ask from user for element in name: print(eval("f'" + f"{user_input}" + "'"))

© www.soinside.com 2019 - 2024. All rights reserved.