为什么 f 字符串需要在赋值表达式两边加上括号?

Ani*_*nil 15 python f-string python-assignment-expression

在 Python (3.11) 中,为什么在 f 字符串内使用赋值表达式(“海象运算符”)时需要用括号括起来?

例如:

#!/usr/bin/env python

from pathlib import Path

import torch


DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")

ckpt_dir = Path("/home/path/to/checkpoints")

_ckpt = next(ckpt_dir.iterdir())
print(_ckpt)
sdict = torch.load(_ckpt, map_location=DEVICE)

model_dict = sdict["state_dict"]

for k, v in model_dict.items():
    print(k)
    print(type(v))
    print(_shape := v.size())
    print(f"{(_numel := v.numel())}")
    print(_numel == torch.prod(torch.tensor(_shape)))
Run Code Online (Sandbox Code Playgroud)

上面的代码块 withprint(f"{_numel := v.numel()}")相反不会解析。

解析/AST 创建是否要求这样做?

Bri*_*ian 22

此行为在原始 PEP中已明确指定中为赋值表达式(也称为海象运算符)

\n

这样做的原因是为了保持与格式化字符串文字的向后兼容性。在添加赋值表达式之前,您已经可以编写类似 的 f 字符串f"{x:=y}",这意味着“x使用格式规范的格式”=y格式化”。

\n

引用PEP 572 \xe2\x80\x93 赋值表达式

\n
\n

f 字符串内的赋值表达式需要括号。例子:

\n
>>> f\'{(x:=10)}\'  # Valid, uses assignment expression\n\'10\'\n>>> x = 10\n>>> f\'{x:=10}\'    # Valid, passes \'=10\' to formatter\n\'        10\'\n
Run Code Online (Sandbox Code Playgroud)\n

这表明 f 字符串中看起来像赋值运算符的东西并不总是赋值运算符。f 字符串解析器使用:指示格式化选项。为了保持向后兼容性,f 字符串内部的赋值运算符的使用必须加上括号。如上所述,不建议使用赋值运算符。

\n
\n


Ahm*_*AEK 6

冒号:和 都=在 f 字符串中具有含义,而 walrus 的:=作用与冒号相同:

x = 4
print(f"{x=}")  # prints "x = 4"
print(f"{x:10}")  # prints output in 10 spaces
print(f"{x:=10}")  # does same as :
Run Code Online (Sandbox Code Playgroud)

反汇编{x:=10}只是加载=10并将其传递给冒号格式操作。

  5           4 LOAD_GLOBAL              0 (print)
              6 LOAD_FAST                0 (x)
              8 LOAD_CONST               2 ('=10')
             10 FORMAT_VALUE             4 (with format)
             12 CALL_FUNCTION            1
             14 POP_TOP
             16 LOAD_CONST               0 (None)
             18 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

  • 为了澄清,“=”指定在符号之后、数字之前放置填充。将 `x` 设置为负值将显示 `f"{x:10}"` 和 `f"{x:=10}"` 之间的差异。 (8认同)