f-字符串中的空格导致 ValueError: 无效的格式说明符。

4

我和同事刚刚遇到了一个使用f-string的有趣问题。这是一个最小化的例子:

>>> f"{ 42:x}"
'2a'

在十六进制类型后添加空格会导致 ValueError
>>> f"{ 42:x }"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Invalid format specifier

我理解 PEP 498 中的段落 Leading and trailing whitespace in expressions is ignored 的意思是实际上应该忽略空格。

为什么空格会导致错误,这背后的原因是什么?


2
语法为 { <expression> <可选 !s、!r 或 !a> <可选 : 格式说明符> },遵循 PEP 498。42 是表达式,x 是格式说明符,而 : 则是分隔符;它们并不是表达式的一部分。 - Amadan
3
空格实际上可以成为格式说明符的一个有意义的部分,因此空格不能被忽略。 - khelwood
1
谢谢!我刚刚查看了PEP 3101," "确实是“sign”选项的有效值。 - Stefan Scheller
1个回答

7

根据您分享的链接:

为了易读性,表达式中的前导和尾随空格将被忽略。这是在评估之前将表达式括在括号中的副产品。

冒号(:)之前的所有内容是该表达式 ([1]),而格式说明符是冒号之后的所有内容。

f-string 中的 { 42 : x } 等同于带有格式说明符 " x "( 42 )

( 42 ) == 42" x " != "x",并且格式说明符会原封不动地传递给对象的 __format__ 方法。

当对象尝试进行格式化时,它无法识别这些位置上的空格(" ") 的含义,并抛出错误。

此外,在某些格式说明符中,空格实际上具有特定的含义,例如作为填充字符符号选项

>>> f"{42: >+5}"  # Width of 5, align to right, with space as fill and plus or minus as sign
'  +42'
>>> f"{42:#> 5}"  # Width of 5, align to right, with `#` as fill and space or minus as sign.
'## 42'

更多信息请查看格式规范迷你语言


1 不包括类型转换,例如!s!r!a


1
“表达式是冒号前的所有内容” - 不完全正确。类型转换也不是表达式的一部分,例如 f'{ 42 !s :10}' 也是一个错误 - Kelly Bundy
@KellyBundy 谢谢你。我添加了一个小注脚,因为我不希望答案过于复杂。 - Bharel

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