从 Python 3.8 开始,代码可以使用所谓的“walrus”运算符(:=
),记录在PEP 572 https://www.python.org/dev/peps/pep-0572/, for 赋值表达式.
这似乎是一个非常重要的新功能,因为它允许在理解和lambda
s.
赋值表达式的语法、语义和语法规范到底是什么?
为什么要引入这个新的(而且看起来相当激进的)概念,尽管PEP 379 https://www.python.org/dev/peps/pep-0379/(提出了“添加赋值表达式”的类似想法)被撤回了?
PEP 572 https://www.python.org/dev/peps/pep-0572/包含许多细节,尤其是第一个问题。我将尝试简洁地总结/引用 PEP 中一些最重要的部分:
基本原理
在推导式中允许这种形式的赋值,例如列表推导式和禁止传统赋值的 lambda 函数。这也可以促进交互式调试,而不需要代码重构。
推荐的用例示例
a) 获取条件值
例如(在 Python 3 中):
command = input("> ")
while command != "quit":
print("You entered:", command)
command = input("> ")
可以变成:
while (command := input("> ")) != "quit":
print("You entered:", command)
同样,从the docs https://docs.python.org/3/whatsnew/3.8.html:
在此示例中,赋值表达式有助于避免调用 len()
两次:
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
b) 简化列表理解
例如:
[(lambda y: [y, x/y])(x+1) for x in range(5)]
可以变成:
[[y := x+1, x/y] for x in range(5)]
语法和语义
在任何可以使用任意 Python 表达式的上下文中,命名表达式可以出现。这是这样的形式name := expr
where expr
是任何有效的 Python 表达式,name 是一个标识符。
这种命名表达式的值与合并的表达式相同,但附加的副作用是目标被分配该值
与常规赋值语句的差异
除了是表达式而不是语句之外,PEP 中还提到了一些差异:表达式赋值从右到左,逗号周围有不同的优先级,并且不支持:
-
多个目标
x = y = z = 0 # Equivalent: (z := (y := (x := 0)))
-
不分配给单个名称的分配:
# No equivalent
a[i] = x
self.rest = []
-
可迭代打包/拆包
# 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
-
内联类型注释:
# Closest equivalent is "p: Optional[int]" as a separate declaration
p: Optional[int] = None
-
不支持增强分配:
total += tax # Equivalent: (total := total + tax)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)