通过海象进行多项分配:=运算符?
Multiple assignments via walrus := operator?
我曾尝试使用海象运算符进行多项赋值,并在 Whosebug 上看到了诸如 this 之类的问题,它也无法使用海象运算符分配多个变量,我只是想知道什么是成功的倍数assignment 会是什么样子,或者是否不可能。
这样做的目的是在 mvdef.src.ast_util
模块中添加对检测我的库 mvdef (specifically, within the find_assigned_args
函数中所有分配的变量名的支持。
从 运行 ast.parse
我可以看到 :=
运算符生成一个 ast.NamedExpr
节点,它有一个 .target
属性,它是一个 ast.Name
对象,我可以从对象的 .id
属性中获取分配的名称。
如果非要我猜的话,我会假设 .target
属性将是 ast.Name
个对象的列表,而不是单个 ast.Name
对象,但是事实上我似乎无法得到一个这样的例子,这让我想知道它是否不可能,至少目前是这样(在这种情况下,我可以简化我的代码,而不仅仅是猜测一个实现应该是)。
如果有人知道要查看 Python 源代码的哪个特定部分来告诉我这是否可行,那将很有帮助,谢谢!
P.S。 - 通过查看 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)")
Iterable packing and unpacking是=
和:=
的一个区别,只有前者支持。在 PEP-572:
中找到
# Equivalent needs extra parentheses
loc = x, y # Use (loc := (x, y))
info = name, phone, *rest # Use (info := (name, phone, *rest))
# No equivalent
px, py, pz = position
name, phone, email, *other_info = contact
简短的回答是你不能用海象做多重赋值——:=
但在我看来,这不是一个明显的缺点,因为有办法解决它。
我们总是可以用一个将 return 的其余值作为输入参数的函数来包装 return 多个值的函数。
考虑以下示例:
if not (userNameCapture := icm.subProc_bashOut(
f"""grep Username: {plonePasswdFile} | cut -d ":" -f 2""",
outcome=cmndOutcome,)): return icm.EH_badOutcome(cmndOutcome)
在这里我得到 stdout 作为主要 return 值,我在 outcome
.
中得到 stderr
一切都很好,我们最终得到了海象和多重分配的好处。
我曾尝试使用海象运算符进行多项赋值,并在 Whosebug 上看到了诸如 this 之类的问题,它也无法使用海象运算符分配多个变量,我只是想知道什么是成功的倍数assignment 会是什么样子,或者是否不可能。
这样做的目的是在 mvdef.src.ast_util
模块中添加对检测我的库 mvdef (specifically, within the find_assigned_args
函数中所有分配的变量名的支持。
从 运行 ast.parse
我可以看到 :=
运算符生成一个 ast.NamedExpr
节点,它有一个 .target
属性,它是一个 ast.Name
对象,我可以从对象的 .id
属性中获取分配的名称。
如果非要我猜的话,我会假设 .target
属性将是 ast.Name
个对象的列表,而不是单个 ast.Name
对象,但是事实上我似乎无法得到一个这样的例子,这让我想知道它是否不可能,至少目前是这样(在这种情况下,我可以简化我的代码,而不仅仅是猜测一个实现应该是)。
如果有人知道要查看 Python 源代码的哪个特定部分来告诉我这是否可行,那将很有帮助,谢谢!
P.S。 - 通过查看 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)")
Iterable packing and unpacking是=
和:=
的一个区别,只有前者支持。在 PEP-572:
# Equivalent needs extra parentheses
loc = x, y # Use (loc := (x, y))
info = name, phone, *rest # Use (info := (name, phone, *rest))
# No equivalent
px, py, pz = position
name, phone, email, *other_info = contact
简短的回答是你不能用海象做多重赋值——:=
但在我看来,这不是一个明显的缺点,因为有办法解决它。
我们总是可以用一个将 return 的其余值作为输入参数的函数来包装 return 多个值的函数。
考虑以下示例:
if not (userNameCapture := icm.subProc_bashOut(
f"""grep Username: {plonePasswdFile} | cut -d ":" -f 2""",
outcome=cmndOutcome,)): return icm.EH_badOutcome(cmndOutcome)
在这里我得到 stdout 作为主要 return 值,我在 outcome
.
一切都很好,我们最终得到了海象和多重分配的好处。