简介
Python3.8版本在2019年10月14号正式发布,此次更新内容当中两个新特性值得一提,分别是新的赋值表达式和仅限位置形参。截止目前anaconda官网还没有整合Python3.8,所以我只能去Python官方直接下载该版本尝尝鲜。
赋值表达式
新增的语法:=
可在表达式内部为变量赋值。因为酷似海象的眼睛和鸭翅,又被昵称为“海象运算符”。
赋值表达式的语法是这样的name := expression
,形式上看和赋值语句=
差不多,但是在使用的时候有点讲究。
直接来看例子:
我们要对列表中的元素个数进行判断,当其大于 4个的时候打印出个数,我们可以这样写。
1 2 3 4 5 6 |
>>> a = [1, 2, 3, 4, 5] >>> n = len(a) >>> if n > 4: print(n) 5 |
在这里使用n=len(a)
获得列表的长度,在if
语句中并不能先赋值再比较。比如下面语法:
1 2 3 |
>>> a = [1, 2, 3, 4, 5] >>> if (n=len(a)) > 4: # SyntaxError: invalid syntax print(n) |
此时就会报错,但是新的赋值语法就能解决这个问题。如果考虑以下语法:
1 2 3 4 5 |
>>> a = [1, 2, 3, 4, 5] >>> if (n:=len(a)) > 4: print(n) 5 |
使用新的语法:=
可在表达式内部为变量赋值。可以看出,形式上和赋值语句=
差不多,就作用上来看也雷同。也就是说=
不是必不可少的,它只是一个锦上添花的新语法。当然也有人说这样反而会使得程序很难读懂,一点都不pythonic,我觉得这都是仁者见仁智者见智的事。
除此之外,我们可以单独比较下在常规情况下的赋值区别:
1 2 3 4 5 6 7 8 9 |
>>> a = 10 >>> a 10 >>> b := 2 # SyntaxError: invalid syntax >>> (b := 2) 2 >>> b 2 |
直接使用b := 2
会报错,但是加了括号以后不仅完成了b
的赋值,而且(b := 2)
本身就等于2。
事实上,该特性比较好的用处是:
1 2 3 4 5 6 7 8 9 |
# 一 简化 os.fork if pid := os.fork(): # Parent code else: # Child code # 二 直接到把 socket 对象的 read buffer 读完为止 while data := sock.recv(8192): print("Received data:", data) |
仅限位置形参
仅限位置形参通过语法/
来实现,它用来指明某些函数形参必须使用仅限位置而非关键字参数的形式。
1 2 |
def f(a, b, /, c, d, *, e, f): print(a, b, c, d, e, f) |
在定义的函数f
当中,符号/
之前的形参a
和b
为仅限位置形参,c
或d
可以是位置形参或关键字形参,而*
后面的e
或f
要求为关键字形参(在没有可变参数的情况下(有,则不用加*
),必须加一个*
号作为特殊分隔符)。
1 2 3 4 5 |
# 合法 f(10, 20, 30, d=40, e=50, f=60) # 不合法 f(10, b=20, c=30, d=40, e=50, f=60) # b cannot be a keyword argument f(10, 20, 30, 40, 50, f=60) # e must be a keyword argument |
目前我觉得这种写法的一个好处是将形参标记为仅限位置形参将允许在未来修改形参名而不会破坏客户的代码。比如:
1 2 |
def quantiles(dist, /, *, n=4, method='exclusive') pass |
由于在/
左侧的形参不会被公开为可用关键字,其他形参名仍可在**kwargs
中使用:
1 2 3 4 5 |
>>> def f(a, b, /, **kwargs): ... print(a, b, kwargs) ... >>> f(10, 20, a=1, b=2, c=3) # a and b are used in two ways 10 20 {'a': 1, 'b': 2, 'c': 3} |
首先按照位置传递10和20给位置参数a
和b
,此时后面的a=1
和b=2
就不再是函数定义中最前面的a
和b
的关键字参数了,/
相当于给了前面的参数一个黑箱,即使调用了黑箱中的参数名也不会赋值给它。这样的好处是防止人为造成的参数传递错误。
其实这个特性就是让函数的编写更加规范,在参数的使用上可以参考这篇文章,非常详细的介绍了参数的使用顺序,相信对大家有帮助。
总结
Python3.8新增的这两项特性都是比较不错的功能(存在即合理),以后应该多多灵活运用到实际生产中^_^。