赋值表达式(Assignment Expressions)
Python3.8 正式版本在前两天已经发布,喜欢尝鲜的同学可以下载下来体验一下,我并没有打算升级到最新版本,因为性能上并没有显著提升。但还是有必要了解其中的新特性。
赋值表达式的语法是:“ name := expression ”,这个曾经引起很大争议特性,最终还是加入到了Python3.8。不过它也仅仅只是一个锦上添花的特性。
我们可以通过一个例子来了解它的使用场景。
>>> import re
>>> data = "hello123world"
>>> match = re.search("(\d+)", data) # 3
>>> if match: # 4
... num = match.group(1)
... else:
... num = None
>>> num
'123'
代码很简单,就是一个使用正则表达式提取字符串中数字部分的操作。之前的做法是先将调用 re.search 方法,返回Match对象,然后赋值给变量 match,再判断 match 对象是否为None来提取其中的数字部分。
在Python3.8中,你可以将第3、4行代码合并成一行代码,在 if 语句中,可以给变量赋值,这就是赋值表达式。相比之前的版本,代码少了一行。
>>> if match:=re.search("(\d+)", data):
... num = match.group(1)
... else:
... num = None
...
>>> num
'123'
总结
这样看起来代码确实精简了一点点,但是,这样的特性对开发者来说,只能说是一个不痛不痒的功能。
仅位置参数(Positional-Only Arguments)
函数传递参数的方式繁多,有位置参数、默认参数、可变参数、关键字参数、命名关键字参数。
举个例子:
def add(x, y, *args, **kwargs):
print(f"x={x}, y={y}")
这里的 x 和 y 就是两个位置参数,我们可以这样调用
add(1, 2)
x=1, y=2
因为是位置参数,严格遵守位置顺序。
不过,你也可以把 x 和 y 当做命名关键字参数进行传递,参数的顺序可改变,例如把 y 放前面,不影响结果
add(y=2, x=1)
x=1, y=2
第二种方式看似更灵活,出错的风险也增加了,特别是多人合作的项目中,例如后期如果有人将该函数的参数名字修改后,调用该函数就报错了。
那么如何从语法层面上禁止这样调用,避免出错呢?
这里就可以使用Python3.8中的仅位置参数语法了,在函数定义时,参数之间可指定一个斜杠(/),斜杠前的参数严格遵守仅位置参数的定义,例如:
def add(x, y, /, *args, **kwargs):
... print(f"x={x}, y={y}")
...
>>> add(1,2)
x=1, y=2
"/" 告诉解释器,x 和 y 是两个严格的位置参数,不能当做命名关键字参数进行传递。如果把它当作命名关键字参数进行传递参数时,会怎么样呢?
add(y=2, x=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 2 required positional arguments: 'x' and 'y'
报错了,系统不允许你使用这种方式调用,仅支持位置参数的方式进行调用,调用时不能指定参数的名字。
总结
仅位置参数的语法就是在函数定义时,位置参数用 “/” 进行分隔,调用时不允许使用命名关键字参数进行调用
f-strings调试
f-strings 是Python3.6中的新特性,Python3.8 中 f-strings 开始支持“=”操作,主要作用是方便用于调试。它的语法是:f'{expr=}' 。
写Python代码,我大部分时候都会用 print 函数调试,因为简单方便,如pdb、pycharm的断点调试功能只在少数特殊场景下才会使用。使用print 函数有什么问题呢?
在代码很长的复杂场景,你可能要打印好几个值,例如:
name1 = "zhang"
name2 = "li"
name3 = "wang"
print(name1)
print(name2)
print(name3)
输出:
zhang
li
wang
从输出结果来看,我们不知道哪个值对应的是哪个变量,在代码行数少的时候还能通过看源代码分辨出来,如果代码量很长很长时,就很容易搞混,不知你有没有遇到过,反正我经常为了区分谁是谁,打印时要加奇形怪异的特殊字符。
当然,在 print 时直接把变量名字打印出来是最直白的。
name1 = "zhang"
name2 = "li"
name3 = "wang"
print(f"name1={name1}")
print(f"name2={name2}")
print(f"name3={name3}")
输出:
name1=zhang
name2=li
name3=wang
为了调试方便,python3.8在f-strings中可以使用等号“=”,打印出来时,等号左边就是变量的名字,右边是对应的值。
name1 = "zhang"
name2 = "li"
name3 = "wang"
print(f"{name1=}")
print(f"{name2=}")
print(f"{name3=}")
输出:
name1=zhang
name2=li
name3=wang
再举个例子:
now = datetime.datetime.now()
>>> print(f"{now.day=}")
now.day=21
总结
简单明了,让世界更加美好
未完待续...
想要了解更多,请点击https://docs.python.org/zh-cn/3/whatsnew/3.8.html
郑重声明
我不是知识的生产者,只是知识的学习者,搬运者,分享者,愿你我一起成长。
本文来自:
https://foofish.net/pep572.html
https://foofish.net/pep457.html
https://foofish.net/fstring-debug.html