说明
《Python 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
Python 的赋值表达式,有时也称为命名表达式(named expression)或海象运算符(walrus operator),它将表达式赋值给标识符,同时还返回表达式的值。它可以一个变量名后跟一个表达式或者一个值,这个和赋值运算符 = 类似,可以看作是一种新的赋值运算符。
昵称为海象运算符是因为:=很像海象「眼睛小,长着两枚长长的牙」这个特点^_^。
一些使用方法:
# if 中
if (a := 11) > 10:
print(a)
# 11
a = range(3)
if (n := len(a)) > 2:
print(n)
# 3
if (x:=sum(range(100))) > 1000:
print(x)
else:
0
# 4950
# while 中
x = 0
while (x:= x+1) < 5:
print(x)
'''
1
2
3
4
'''
while (psw := input("请输入密码:")) != "123":
print('密码', psw, '不正确!')
continue
print('登录成功!')
# 列表推导式
[m:=i for i in range(100)]
m
# 99
[n for i in range(10) if (n:=i%5)]
# [1, 2, 3, 4, 1, 2, 3, 4]
以上示例中,if (n := len(a)) > 2
和不带括号的 if n := len(a) > 2
逻辑不一样,后者 n 为海象符号后边的表达式 len(a) > 2
的值,是一个布尔值。
命名表达式允许使用描述性名称代替较长的表达式,并允许重用。赋值表达式的语法是:
identifier := expression or value
NAME := expr
标识符号 := 表达式
赋值表达式在被用作表达式语句及在被用作切片、条件表达式、lambda 表达式、关键字参数和推导式中的 if 表达式以及在 assert, with 和 assignment 语句中的子表达式时必须用圆括号括起来。 在其可使用的其他场合,圆括号则不是必须的,包括在 if 和 while 语句中。
一个常见用例是在处理匹配的正则表达式的时候:
if matching := pattern.search(data):
do_something(matching)
或者是在处理分块的文件流的时候:
while chunk := file.read(9000):
process(chunk)
其他的一些场景:
# 处理匹配的正则表达式
if (match := pattern.search(data)) is not None:
# Do something with match
# 使用已经计算后的值
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]
这是 Python 3.8 新版功能,请参阅 PEP 572 了解有关赋值表达式的详情。
海象运算符同样适合用于字典推导式和集合推导式。
在合适的场景中使用海象运算符可以降低程序复杂性,简化代码,可以写出优雅而简洁的 Python 代码。
海象运算符很新颖并且有争议,但是只有时间会见证它逐渐被大家接收。
PEP572 的标题是「Assignment Expressions」,也就是「赋值表达式」,也叫做「命名表达式」,不过它现在被广泛的别名是「海象运算符」(The Walrus Operator)。
解决的核心问题是求值过程中也赋值了新的中间变量,这个(些)中间变量可以在代码块中被继续使用。
对于3.8版本的这个运算符的加入,有很多的声音,围绕海象运算符(PEP572)的争议非常多,而且由此引发的「战争」导致了 Python 之父 Guido van Rossum 告退,不再担任 Python 社区的终身仁慈独裁者(BDFL)。
虽然赋值表达式的引入是为了更高效地编写代码,但 van Rossum 在网上遭到了反对者的严厉批评,一些人认为这一提案会降低代码的可读性和可维护性。
van Rossum 说,虽然他已经习惯了围绕新功能而展开的争论,但这次有人诋毁他,他们的态度十分强硬,甚至有人对他进行人身攻击,所以他决定辞职。
他说:“那些在技术上持不同意见的人在社交媒体上开始抱怨我破坏了 Python 的决策流程,或者说我犯了一个严重的错误。我感到非常失望,我感觉受到了来自背后的攻击”。
“过去,在决定是否要对 Python 做出变更或改进时,一群核心开发人员会讨论这件事的利弊。他们会得出一个明确的共识,如果结果不明确,我会在脑子里反复考虑,然后做出决定。在 PEP572 这个提案上,尽管它存在争议,但我还是选择了“是的,我想做这个”,但人们并不买账。
“这并不是一种反叛,但我觉得我没有得到核心开发者社区足够多的信任”。
他认为,Python 的争议方式之所以发生变化,部分原因在于现在有太多的人使用 Python。
我们在一般的列表推导式中,我们无法获取中间变量,比如,我们可以通过下边的改变得到最后一次的中间变量值。
[v for v in range(3)]
v
# NameError: name 'v' is not defined
# 计算列表的部分和
total = 2
partial_sums = [total := total + v for v in range(3)]
print("Total:", total)
# Total: 5
f 字符串中的赋值表达式需要括号。例子:
f'{(x:=3)}'*x
# '333'
但这与以下方法容易混淆,不推荐使用:
f'{x:=10}'
# ' 3'
直接判断字典值,并赋值中间变量并使用:
d = {'a': 1, 'b': 2}
if (x:= d.get('a')) > 0:
print(x)
# 1
记录以表达式传入函数参数时表达式的值。例子:
def foo(x):
print(x**2)
foo(3)
# 9
foo(n:=sum(range(5)))
# 100
# 传入的值
n
# 10
更新时间:May 28, 2024, 2:47 p.m. 标签:python 赋值 表达式 海象符