浅析PEP572: 海象运算符
作者:小明 发布时间:2023-06-28 10:56:10
现在已经是Python 3.8的最后一个alpha版本,接着就是本月底要发布的的3.8.0 beta 1了。按规定,3.8已经不会再添加(修改)功能了,之前非常有争议的PEP 572的实现已经算是很固定了,我们这篇文章就来先尝个鲜。看看这个新的赋值表达式语法怎么用,何时用。
海象运算符
PEP572的标题是「Assignment Expressions」,也就是「赋值表达式」,也叫做「命名表达式」,不过它现在被广泛的别名是「海象运算符」(The Walrus Operator)。因为:=很像海象「眼睛小,长着两枚长长的牙」这个特点^_^。
语法和语义
我们不详细介绍PEP的内容,直接说应用场景。我觉得它主要可以用在2个地方
赋值给中间变量
这个小标题想了很久,没找到更合适能表达的。不过相信通过2个例子相信大家就能理解了。
首先是一个正则匹配的例子:
pattern = re.compile('s')
data = 'ss'
if pattern.match(data):
print(pattern.match(data).group(0))
如果能匹配到条件,match 对象才会有group 方法。但是这样写虽然节省到一行代码却让执行变慢了,因为重复地执行了2次re.match(data)。正确的写法是:
match = pattern.match(data)
if match:
print(match.group(0))
代码也就只能写成这样了,但如果使用赋值表达式:
if (match := pattern.match(data)) is not None:
print(match.group(0))
本来if这种控制结构语句只是求值表达式,看结果是不是符合条件。而在这里,它做了3件事:
对表达式pattern.match(data)求值
把值的结果赋值给match
把match 作为if的条件,判断它的值是不是None
我对它的理解是: 求值过程中也赋值了新的中间变量,这个(些)中间变量(如这里的match)可以在代码块中被继续使用。
再看一个文件读取的例子:
while 1:
line = fp.readline()
if not line:
break
print(line)
现在可以直接写成:
while (line := fp.readline()):
print(line)
这可以说是一种代码风格的改进了。
简化列表解析
列表解析性能好,而且非常 pythonic,但是它应用场景有限,我们看个例子:
results = []
for x in data:
result = f(x)
if result:
results.append(result)
这是一个日常开发里面比较常见的结构。现在是不能用列表解析的,不信的话下面的方案:
results = [
f(x) for x in data
if f(x)
]
这个是错误的,每次循环执行了2 次f函数。现在用赋值表达式可以写成:
results = [
y for x in data
if (y := f(x))
]
可以用列表解析了!
再看一个PEP提的例子:
stuff = [[y := f(x), x/y] for x in range(5)]
其实又回到了赋值给中间变量这个点,每一项包含了y,以及要用y才能获得结果的x/y。
上面说的就是海象运算符能实现的目的了~
Golang里面的:=
:=并不是Python首创的,Golang里面有一个短变量声明(Short variable declarations)语法:
// ShortVarDecl = IdentifierList ":=" ExpressionList .
i, j := 0, 10
f := func() int { return 7 }
func f(n int) (res int, err error) {
if _, err := f(n-1); err != nil {
return
}
return
}
:=的作用是替代 var 定义,声明时不需要指定类型。同时由于语言设计,和Python的赋值表达式一样,如上面的例子,f(n-1)的第二个返回值err可以被后面的err != nil使用,用来判断条件是否成立,我非常喜欢!
我对PEP 572的看法
在之前我曾经在知乎回答过「如何看待 PEP 572 ?」这个问题,当时我这么说:
这个PEP 有明确的 Recommended use-cases, 在正确的地方使用,而不是滥用,当然不喜欢的可以不用,用旧的形式。我语言提供了更多特性和选择的机会,但控制权是开发者手里的,就像元类、描述符、dataclass 甚至装饰器等等都是有适用场景的。
有人觉得它不符合Python之禅,其实我个人感觉挺好的呀。现在PEP 572的实现已经合并到Python3.8,试用下来非常赞。
Dustin Ingram在PyCON2019上做了一个《PEP 572: The Walrus Operator》的分享,最后他也说自己不喜欢这个语法,但是他接着说:
You might say well i don't like it, that's totally fine. you don't have to like it if you don't like it then don't write it
我觉得说的非常好,没人强制你必须使用它~
好了,本文就给大家介绍到这里,希望对大家有所帮助!
来源:https://zhuanlan.zhihu.com/p/67192546
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- zip通常用于将两个列表合并在一起以同时进行迭代遍历注意:直接使用zip输出结果为<zip at 0x1d72cf30bc8>,
- 简介:使用python的过程中肯定少不了读取文件的操作,传统的形式是使用 直接打开、然后在操作、然后再关闭,这样代码量稍微大些不说,一旦在操
- 引入:if-else的作用,满足一个条件做什么,否则做什么。if-else语句语法结构if 判断条件:要执行的代码else:要执行的代码判断
- 网页的圆角处理,其实最开始的九宫格的表格处理是挺方便的,只是现在都不用表格布局了,自然就被非法取缔了。呵呵。微软的有VML画圆角,由于只是它
- 本文实例讲述了Python实现的大数据分析操作系统日志功能。分享给大家供大家参考,具体如下:一 代码1、大文件切分import osimpo
- js:controller:
- 安装lodashnpm i --save-dev @types/lodash在组件中引入lodashimport * as _ from &
- 导语:哈喽,哈喽~小编不知道你有没有经历过,想联系一位很长时间没有联系的朋友,发现对方很早以前已经把你删除了,而你还一无所知。反正小编经历过
- 今天在研究Plotly绘制散点图的方法,供大家参考,具体内容如下使用Python3.6 + PlotlyPlotly版本2.0.0在开始之前
- 本文实例讲述了django框架实现一次性上传多个文件功能。分享给大家供大家参考,具体如下:在用django 写文件上传的时候,从reques
- 一、安装mysqlclient网上看到很过通过命令:pip install mysqlclient 进行安装的教程,但是我却始终安装失败,遇
- UPDATE语句的速度更新查询的优化同SELECT查询一样,需要额外的写开销。写速度依赖于更新的数据大小和更新的索引的数量。没有更改的索引不
- 废话不多说,直接上代码create database mydbuse mydbgocreate table account( i
- 使用el-upload 上传视频总是报404错误,具体也不知道什么原因(如有知道的请评论告知,谢谢),去网上查了很多,代码写法确定
- 问题简述在 Windows 系统上,我使用 Python 3.11 的 pip 工具安装 lxml 等库时会出现以下报错:error: Mi
- 本文实例讲述了python二分查找算法的递归实现方法。分享给大家供大家参考,具体如下:这里先提供一段二分查找的代码:def binarySe
- 本文实例总结了python格式化字符串的方法,分享给大家供大家参考。具体分析如下:将python字符串格式化方法以例子的形式表述如下:* 定
- 本文详细罗列归纳了Python常见数据结构,并附以实例加以说明,相信对读者有一定的参考借鉴价值。总体而言Python中常见的数据结构可以统称
- 本文实例讲述了Python单元测试方法。分享给大家供大家参考,具体如下:Eric书中《Python编程从入门到实践》中的一个例子。《Pyth
- torch.nn.Conv2d中自定义权重torch.nn.Conv2d函数调用后会自动初始化weight和bias,本文主要涉及如何自定义