Python 3.8正式发布重要新功能一览
Python3.8有哪些你要关注的新内容?
Python3.8都有哪些新功能,在文档手册中,大家可以有一个概览。这么多新内容,哪些是大家最先要关注一下的呢?下面,营长就带大家从深度和广度两方面,了解那些最大的变化,帮助大家快速上手Python3.8.
新功能手册:
https://docs.python.org/3.8/whatsnew/3.8.html
在本文中,你将了解到Python3.8如何:
- 使用赋值表达式简化一些代码结构
- 在你自己的函数中强制执行仅位置参数
- 指定更精确的类型提示
- 使用f字符串进行更简单的调试
除了少数例外,Python3.8对早期版本进行了许多小的改进。在本文结尾处,你将看到许多这些不太引人注意的更改,并讨论了一些使Python3.8比其先前版本更快的优化。最后,你还会获得一些有关升级到新版本的建议。
一、赋值表达式(Assignmentexpressions)
引入赋值表达式,可以说是Python3.8中最大的一个变化了。注意,现在已经用新的符号了(:=),形似海象侧牙,也被称为“海象运算符”。赋值表达式可以在统一表达式中赋值并返回值,比如下面的代码,执行给变量分配值,并打印这个值
>>>walrus=False >>>print(walrus) False Python3.8中,可以使用walrus运算符将上面两个语句合并为一句 >>>print(walrus:=True) True
赋值表达式可以把True分配给walrus,并直接print这个值。一定要有(:=),不然表达式也是无法正常执行的,有了新的赋值表达式符号,不仅在构造上更简便,有时也可以更清楚的传达代码意图。
比如,在while循环中,就体现了(:=)的优势
inputs=list() current=input("Writesomething:") whilecurrent!="quit": inputs.append(current) current=input("Writesomething:")
上面的这段代码并不够优秀,需要不断重复input语句,并且需要以某种方式加到current列表中,然后在执行后面的代码,更好的解决方案是设置一个无限while循环,然后用break停止循环
inputs=list() whileTrue: current=input("Writesomething:") ifcurrent=="quit": break inputs.append(current)
这段代码与上面的代码是等效的,不过,如果使用赋值表达式,还可以再进一步简化这段循环:
inputs=list() while(current:=input("Writesomething:"))!="quit": inputs.append(current)
现在的代码虽然更简化了,但是可读性就变差了,所以,大家要使用赋值表达式的方法还需要结合自身进行判断。
PEP572中描述了复制表达式的所有细节,大家可以深入阅读。
https://www.python.org/dev/peps/pep-0572/https://www.python.org/dev/peps/pep-0572/#examples
仅位置参数(Positional-OnlyArguments)
内置函数float()可用于将文本字符串和数字类型转换成float对象,如下面的代码
>>>float("3.8") 3.8 >>>help(float) classfloat(object) |float(x=0,/) | |Convertastringornumbertoafloatingpointnumber,ifpossible. [...] float(/)中(/)是什么意思?有关这部分内容的讨论可以参考下面的文档,今天的内容中不做为我们的重点内容 PEP457--NotationForPositional-OnlyParameters https://www.python.org/dev/peps/pep-0457/
事实证明,虽然float()调用了参数x,但并不允许使用其名称
>>>float(x="3.8") Traceback(mostrecentcalllast): File"",line1,in TypeError:float()takesnokeywordarguments
使用float()时,只允许按位置指定参数,而不能使用关键字参数。Python3.8之前,这类仅位置参数只适用于内置参数,在我们自己定义的函数中,没有简单的方法指定参数为仅位置参数。
>>>defincr(x): ...returnx+1 ... >>>incr(3.8) 4.8 >>>incr(x=3.8) 4.8
上面这段代码使用了*args,模拟了仅位置参数,但是不够灵活,不易读,而在Python3.8中,可以用/来表示必须通过仅位置参数之前的参数,可以重写incr()接收位置参数:
>>>defincr(x,/): ...returnx+1 ... >>>incr(3.8) 4.8 >>>incr(x=3.8) Traceback(mostrecentcalllast): File"",line1,in TypeError:incr()gotsomepositional-onlyargumentspassedas keywordarguments:'x'
通过在x之后加入/,就可以指定x为仅位置参数。常规参数与仅位置参数结合使用,可将常规参数放在/之后:
>>>defgreet(name,/,greeting="Hello"): ...returnf"{greeting},{name}" ... >>>greet("Łukasz") 'Hello,Łukasz' >>>greet("Łukasz",greeting="Awesomejob") 'Awesomejob,Łukasz' >>>greet(name="Łukasz",greeting="Awesomejob") Traceback(mostrecentcalllast): File"",line1,in TypeError:greet()gotsomepositional-onlyargumentspassedas keywordarguments:'name'
greet()中,/放在name和greeting之间,表示name是仅位置参数,greeting是可以通过位置或关键字传递的常规参数。
大家可能觉得仅位置参数的可读性似乎并不好,但是使用后会发现,很多情况下,只有仅位置参数可以优化我们的代码。此外,使用仅位置函数还有一个好处,可以更轻松地重构函数,更改函数的名称时,不必担心给其他代码带来的影响。仅位置函数还很好的补充了仅关键字参数,可以使用*指定仅关键字参数:
>>>defto_fahrenheit(*,celsius): ...return32+celsius*9/5 ... >>>to_fahrenheit(40) Traceback(mostrecentcalllast): File"",line1,in TypeError:to_fahrenheit()takes0positionalargumentsbut1wasgiven >>>to_fahrenheit(celsius=40) 104.0
上段代码中,celsius是仅关键字参数。
还可以通过按/和分隔的顺序组合仅位置、常规和仅关键字参数*,例如下段代码中,text是仅位置参数,border是常规参数(值为默认值),并且width是仅关键字参数(值为默认值):
>>>defheadline(text,/,border="♦",*,width=50): ...returnf"{text}".center(width,border) ...text是仅位置参数,因此不能使用关键字text: >>>headline("Positional-onlyArguments") '♦♦♦♦♦♦♦♦♦♦♦Positional-onlyArguments♦♦♦♦♦♦♦♦♦♦♦♦' >>>headline(text="Thisdoesn'twork!") Traceback(mostrecentcalllast): File"",line1,in TypeError:headline()gotsomepositional-onlyargumentspassedas keywordarguments:'text' border既可以使用关键字,也可以不使用关键字指定: >>>headline("Python3.8","=") '===================Python3.8===================' >>>headline("RealPython",border=":") '::::::::::::::::::RealPython:::::::::::::::::::'
最后,width必须用关键字指定:
>>> >>>headline("Python","