【发布时间】:2020-01-02 16:59:30
【问题描述】:
我尝试使用 walrus 运算符进行多项赋值,并在 StackOverflow 上看到诸如 this 之类的问题,它也无法使用 walrus 运算符分配多个变量,我只是想知道成功的多重赋值会是什么样子,或者是否不可能。
这样做的目的是增加对在我的库mvdef(特别是在mvdef.src.ast_util 模块中的find_assigned_args 函数内)检测所有已分配变量名称的支持。
通过运行ast.parse,我可以看到:= 运算符产生了一个ast.NamedExpr 节点,它有一个.target 属性,它是一个ast.Name 对象,我可以从中获取分配的名称对象的.id 属性。
如果我不得不猜测,我会假设如果有可能,.target 属性将是ast.Name 对象的列表,而不是单个ast.Name 对象,但事实是我似乎无法获得这方面的示例,这让我怀疑这是否不可能,至少目前是这样(在这种情况下,我可以简化我的代码,而不仅仅是猜测实现应该是什么)。
如果有人知道要查看 Python 源代码的哪个特定部分并告诉我这是否可行,那将很有帮助,谢谢!
附: - 通过查看initial commit (via) 中提供的Lib/test/test_parser.py 中的测试用例,似乎没有使用海象运算符进行多次赋值的示例,所以我现在假设它不是可能(但如果我错了,请插话!)
def test_named_expressions(self):
self.check_suite("(a := 1)")
self.check_suite("(a := a)")
self.check_suite("if (match := pattern.search(data)) is None: pass")
self.check_suite("[y := f(x), y**2, y**3]")
self.check_suite("filtered_data = [y for x in data if (y := f(x)) is None]")
self.check_suite("(y := f(x))")
self.check_suite("y0 = (y1 := f(x))")
self.check_suite("foo(x=(y := f(x)))")
self.check_suite("def foo(answer=(p := 42)): pass")
self.check_suite("def foo(answer: (p := 42) = 5): pass")
self.check_suite("lambda: (x := 1)")
self.check_suite("(x := lambda: 1)")
self.check_suite("(x := lambda: (y := 1))") # not in PEP
self.check_suite("lambda line: (m := re.match(pattern, line)) and m.group(1)")
self.check_suite("x = (y := 0)")
self.check_suite("(z:=(y:=(x:=0)))")
self.check_suite("(info := (name, phone, *rest))")
self.check_suite("(x:=1,2)")
self.check_suite("(total := total + tax)")
self.check_suite("len(lines := f.readlines())")
self.check_suite("foo(x := 3, cat='vector')")
self.check_suite("foo(cat=(category := 'vector'))")
self.check_suite("if any(len(longline := l) >= 100 for l in lines): print(longline)")
self.check_suite(
"if env_base := os.environ.get('PYTHONUSERBASE', None): return env_base"
)
self.check_suite(
"if self._is_special and (ans := self._check_nans(context=context)): return ans"
)
self.check_suite("foo(b := 2, a=1)")
self.check_suite("foo(b := 2, a=1)")
self.check_suite("foo((b := 2), a=1)")
self.check_suite("foo(c=(b := 2), a=1)")
【问题讨论】:
-
:=的左侧参数必须是标识符,仅此而已。如果“多重赋值”是指元组解包 (a, b = ...),则根本不允许。 -
来自PEP-572:“其格式为 NAME := expr,其中 expr 是除无括号元组之外的任何有效 Python 表达式,NAME 是标识符。”
-
还要注意规范中的multiple targets are not directory supported。我知道这与解构不同,但它与 @chepner 的 cmets 相伴。
-
啊,好的,感谢 cmets!如果有人想写一个答案,我很乐意接受并关闭。我的意思是“拆包”是的
-
有一个open issue 允许在“海象”运算符的左侧进行元组解包。
标签: python abstract-syntax-tree python-3.8