浅析PEP572: 海象运算符


Posted in Python onOctober 15, 2019

现在已经是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

我觉得说的非常好,没人强制你必须使用它~

好了,本文就给大家介绍到这里,希望对大家有所帮助!

Python 相关文章推荐
python发布模块的步骤分享
Feb 21 Python
python连接mysql调用存储过程示例
Mar 05 Python
python在windows下实现ping操作并接收返回信息的方法
Mar 20 Python
python实现同时给多个变量赋值的方法
Apr 30 Python
python网络编程之文件下载实例分析
May 20 Python
自动化Nginx服务器的反向代理的配置方法
Jun 28 Python
Python 40行代码实现人脸识别功能
Apr 02 Python
详解python上传文件和字符到PHP服务器
Nov 24 Python
python3.7.0的安装步骤
Aug 27 Python
python 实现手机自动拨打电话的方法(通话压力测试)
Aug 08 Python
matplotlib 多个图像共用一个colorbar的实现示例
Sep 10 Python
python opencv图像处理(素描、怀旧、光照、流年、滤镜 原理及实现)
Dec 10 Python
Python 导入文件过程图解
Oct 15 #Python
Python3.8对可迭代解包的改进及用法详解
Oct 15 #Python
Python 3.8正式发布,来尝鲜这些新特性吧
Oct 15 #Python
Python3安装pip工具的详细步骤
Oct 14 #Python
python区分不同数据类型的方法
Oct 14 #Python
django中瀑布流写法实例代码
Oct 14 #Python
python 中Arduino串口传输数据到电脑并保存至excel表格
Oct 14 #Python
You might like
将OICQ数据转成MYSQL数据
2006/10/09 PHP
php curl选项列表(超详细)
2013/07/01 PHP
PHP 获取远程文件大小的3种解决方法
2013/07/11 PHP
php实现的mongodb操作类
2015/05/28 PHP
PHP实现的文件上传类与用法详解
2017/07/05 PHP
php使用json-schema模块实现json校验示例
2019/09/28 PHP
JQuery 简便实现页面元素数据验证功能
2007/03/24 Javascript
Js+Flash实现访问剪切板操作
2012/11/20 Javascript
如何让页面在打开时自动刷新一次让图片全部显示
2012/12/17 Javascript
浅析ajax请求json数据并用js解析(示例分析)
2013/07/13 Javascript
jQuery淡入淡出元素让其效果更为生动
2014/09/01 Javascript
jQuery中:input选择器用法实例
2015/01/03 Javascript
JS简单计算器实例
2015/01/20 Javascript
js的toUpperCase方法用法实例
2015/01/27 Javascript
jquery validate和jquery form 插件组合实现验证表单后AJAX提交
2015/08/26 Javascript
原生JavaScript实现滚动条效果
2020/03/24 Javascript
使用jquery.form.js实现图片上传的方法
2016/05/05 Javascript
基于js对象,操作属性、方法详解
2016/08/11 Javascript
浅谈Node.js CVE-2017-14849 漏洞分析(详细步骤)
2017/11/10 Javascript
extract-text-webpack-plugin用法详解
2019/02/14 Javascript
layui复选框限制选择个数的方法
2019/09/18 Javascript
python实现telnet客户端的方法
2015/04/15 Python
python基础之入门必看操作
2017/07/26 Python
TensorFlow如何实现反向传播
2018/02/06 Python
计算机二级python学习教程(2) python语言基本语法元素
2019/05/16 Python
numpy数组广播的机制
2019/07/12 Python
pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)
2020/06/24 Python
css3实现wifi信号逐渐增强效果实例
2017/08/09 HTML / CSS
HTML5 localStorage使用总结
2017/02/22 HTML / CSS
文科教师毕业的自我评价
2014/01/16 职场文书
市政管理求职信范文
2014/05/07 职场文书
董事长助理工作职责范本
2014/07/01 职场文书
大学考试作弊检讨书
2015/05/06 职场文书
植树节新闻稿
2015/07/17 职场文书
幼儿园班级管理心得体会
2016/01/07 职场文书
2016年教师党员承诺书范文
2016/03/24 职场文书