为什么f-strings不能很好地与字典配合使用?

8

f-strings在与字典一起使用时表现不佳,详见此处

以下是一个不太好的示例:

d = {'foo': 'bar'}

# Both work as expected
d["foo"]
d['foo']

# This only works when different quotations are used in the inner and outer strings
f'{d["foo"]}'
f"{d['foo']}"

# This doesn't work
f'{d['foo']}'
f"{d["foo"]}"

# The .format() method doesn't care
'{}'.format(d['foo'])

最后两个f字符串导致SyntaxError: invalid syntax,这是因为字符串'{d['foo']}'被解析为'{d['foo']}'。为什么f字符串中花括号内的所有内容不像使用旧的.format()方法时那样单独被解析,并且实现f字符串的可能原因是什么?我喜欢f字符串,但这似乎是支持旧方法的理由。

2
如果 ' 不表示单引号,你会如何标记字符串的结尾? - Peter Wood
format 的另一个优点是,你可以省略围绕索引键的字符串分隔符,例如 '{}'.format(d[foo]),除非它们包含数字(或是一个数字),尽管这很奇怪。 - Magnus Lind Oxlund
3个回答

6

F-strings是字面字符串。在相同类型的引号内包含未转义的引号是无效的语法。这很有道理,因为结果是模棱两可的:解释器将不知道字符串何时结束。一种 传统的方法 是使用反斜杠来引用引号。但是 PEP498 禁止在f-字符串的表达式中使用反斜杠:

反斜杠不能出现在f-字符串的表达式部分中...你可以在表达式内部使用不同类型的引号...

因此,在f-string表达式中访问给定键的字典值的唯一方法是使用不同类型的引号。在所有地方使用单引号或双引号是模棱两可的,并会导致 SyntaxError

str.format是一种常规方法,因此工作方式不同:d['foo']在构建字符串之前被计算。就像当你向函数提供参数时,参数在函数执行任何操作之前被计算。


你的回答解释了为什么format表达式被单独评估,但没有解释为什么f-string表达式不是这样。 - Magnus Lind Oxlund
1
@MagnusLindOxlund,我已经更新了我的答案,并认为它充分回答了问题,重点是如何在引号内嵌套引号。 - jpp
1
我同意它展示了如何解决问题,我已经取消了对你回答的踩,但是问题要求解释设计背后的原因。我尝试回答了这个问题。 - Magnus Lind Oxlund

2
这与f字符串无关。一旦评估,f字符串就变成普通字符串。您所尝试的也会是标准字符串的问题。
问题在于:
'a "b" c' 

这段文字解释了字面值 a "b" c 的声明方式。

同时,

'a 'b' c'

引号会关闭并重新打开。因此,它等同于字符串a,后跟变量b,后跟字符串c

这就是Python支持两种引号的完整原因。


F-strings是常见的字符串,但只有在评估之后才能使用。它们存在的全部意义就是在合成字符串时暂停字符串字面量的限制。问题是:既然我们有大括号来标记其中的表达式,为什么f-strings还要受到字符串定界符的限制呢? - Magnus Lind Oxlund

0
根据PEP 498,f-strings依赖于常规字符串文字的实现,因此受到相同约束的限制。除此之外,f-strings还有自己的限制,例如在表达式中任何地方排除反斜杠。
关于实现选择的原理尚未公布,但易于实现、向后兼容、语法高亮和与现有插值语法一致性都在核心开发人员在公开可访问的邮件列表上的讨论中得到了探讨。1 争议的核心问题是所提出的概念是具有特殊属性的字符串还是插入代码的字符串。2 前者更受青睐。PEP 536代表异议意见,并寻求解除若干语法限制。
基于这个讨论,对禁止表达式中的反斜杠进行了初步妥协,只剩下字符串分隔符反转作为f-string表达式中索引字典的唯一剩余选项。
选择在 f-string 引入之前的讨论(Python 3.6):

[Python-ideas] 更简洁的字符串格式
Re: [Python-ideas] 更简洁的字符串格式
Re: [Python-ideas] 更简洁的字符串格式
[Python-ideas] 为所有字面字符串添加插值
[Python-Dev] PEP-498:字面字符串格式化
[Python-Dev] PEP 498 f-string:它是预处理器吗?
[Python-Dev] PEP 498 href="interpolated f-string" 调整
[Python-Dev] 解析 PEP 498 中的 f-string -- 字面字符串插值

[Python-ideas] 让 f-literals 中的转义不可能

但是f-strings甚至不应该看到那些反斜杠,至少传统的词法分析器不会。因此,它们是一种奇怪的、非常奇怪的(并且不符合Python美学的丑陋)混合体。 - Jürgen A. Erhard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接