什么是赋值表达式(使用“海象”或“:=”运算符)?为什么要添加此语法?
- 2025-01-09 08:46:00
- admin 原创
- 15
问题描述:
自 Python 3.8 开始,代码可以使用PEP 572:=
中记录的所谓“海象”运算符 ( )进行赋值表达式。
这似乎是一个非常重要的新功能,因为它允许在理解和lambda
s 中进行这种形式的分配。
赋值表达式的语法、语义和语法规范到底是什么?
为什么会引入这个新的(并且看似非常激进的)概念,即使PEP 379(提出了类似“添加赋值表达式”的想法)已被撤回?
解决方案 1:
PEP 572包含许多细节,尤其是第一个问题。我将尝试简洁地总结/引用 PEP 中一些最重要的部分:
基本原理
允许在推导式(例如列表推导式和禁止使用传统赋值的 lambda 函数)内进行这种形式的赋值。这还可以促进交互式调试,而无需代码重构。
推荐用例示例
a) 获取条件值
例如(在 Python 3 中):
command = input("> ")
while command != "quit":
print("You entered:", command)
command = input("> ")
可以变成:
while (command := input("> ")) != "quit": print("You entered:", command)
同样,从文档中:
在此示例中,赋值表达式有助于避免两次调用 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
其中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)
解决方案 2:
以下是我最喜欢的几个赋值表达式示例,它们可以使代码更简洁、更易于阅读:
if
陈述
前:
match = pattern.match(line)
if match:
return match.group(1)
后:
if match := pattern.match(line):
return match.group(1)
无限while
语句
前:
while True:
data = f.read(1024)
if not data:
break
use(data)
后:
while data := f.read(1024):
use(data)
PEP 中还有其他很好的例子。
解决方案 3:
现在 3.8 版已经正式发布,这里再举几个例子和理由。
命名表达式的结果是编程的一个重要部分,允许使用描述性名称代替较长的表达式,并允许重复使用。目前,此功能仅在语句形式中可用,因此在列表推导和其他表达式上下文中不可用。
来源:LicensedProfessional 的 reddit 评论
处理匹配的正则表达式
if (match := pattern.search(data)) is not None:
# Do something with match
无法使用 2-arg iter() 轻松重写的循环
while chunk := file.read(8192):
process(chunk)
重复使用计算成本高昂的值
[y := f(x), y**2, y**3]
在理解过滤器子句及其输出之间共享子表达式
filtered_data = [y for x in data if (y := f(x)) is not None]
解决方案 4:
什么是 := 运算符?
简单来说:=
就是表达式 + 赋值运算符。它执行一个表达式并将该表达式的结果赋给单个变量。
为什么需要 := 运算符?
一个简单有用的案例是减少理解中的函数调用,同时保持可读性。
让我们考虑一个列表推导,在没有运算符的情况下,如果结果大于 0,则添加一个并过滤:=
。这里我们需要调用该add_one
函数两次。
[add_one(num) for num in numbers if add_one(num) > 0]
案例 1:
def add_one(num):
return num + 1
numbers = [1,2,3,4,-2,45,6]
result1 = [value for num in numbers if (value := add_one(num)) > 0]
>>> result1
[2, 3, 4, 5, 46, 7]
结果符合预期,我们不需要调用该add_one
函数两次,这显示了运算符的优势:=
。
使用列表推导时要谨慎使用海象:=
运算符。
以下案例可能有助于您更好地理解运算符的用法:=
。
案例 2:
def add_one(num):
return num + 1
numbers = [1,2,3,4,-2,45,6]
>>> result2 = [(value := add_one(num)) for num in numbers if value > 0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
NameError: name 'value' is not defined
情况 3:当全局变量设置为正时
def add_one(num):
return num + 1
numbers = [1,2,3,4,-2,45,6]
value = 1
result3 = [(value := add_one(num)) for num in numbers if value > 0]
>>> result3
[2, 3, 4, 5, -1]
情况 4:当全局变量设置为负数时
def add_one(num):
return num + 1
numbers = [1,2,3,4,-2,45,6]
value = -1
result4 = [(value := add_one(num)) for num in numbers if value > 0]
>>> result4
[]
解决方案 5:
海象算子可用于避免某些函数的重新计算。以下是一个例子。
案例 1:
if complexOperation(num) > 90:
result = complexOperation(num)
executeActualFunctionality(result)
案例 2:
if result := complexOperation(num) > 90:
executeActualFunctionality(result)
在案例 1 中,我们执行complexOperation()
两次只是因为我们不确定结果。通过练习案例 2 可以避免这种情况。
注意:我们也可以在语句前声明结果变量if
并计算complexOperation()
一次。
解决方案 6:
没有海象运算符:
card_number = input("Enter card number: ")
if len(card_number) == 8:
print(f"Card {card_number} is valid")
else:
print(f"Card {card_number} is invalid")
使用海象运算符:
if len(card_number := input("Enter card number: ")) == 8:
print(f"Card {card_number} is valid")
else:
print(f"Card {card_number} is invalid")
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理必备:盘点2024年13款好用的项目管理软件