介绍
2020 年 10 月 5 日 Python 3.9 已经发布了正式版,新增了一大波新特性,快来上手尝试一下吧。
知识点
- 字典合并与更新运算符
- 放宽装饰器的语法
- 移除前缀后缀的字符串方法
- datetime 模块
- math 模块
安装 Python3.9
要想使用 Python3.9,首先需要添加 deadsnakes 软件源。
在终端运行下面命令:
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get update
之后根据提醒按下回车键,就会自动安装完成。
运行结果如下:
然后就可以安装 Python3.9 了,后面输入y同意执行
sudo apt install python3.9-full
运行结果如下:
顺便给 Python3.9 安装 pip ,方便安装需要的模块
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" && python3.9 get-pip.py
运行结果如下:
安装之后我们可以进入 Python3.9 交互环境
python3.9
运行结果如下:
字典合并与更新运算符
合并 (|) 与更新 (|=) 运算符已被加入内置的 dict 类。 它们为现有的 dict.update 和 {**d1, **d2} 字典合并方法提供了补充。
在之前版本中,我们要想将 y 合并到 x ,通常会使用 x.update(y) 这样操作有个需要注意的情况,就是它没有返回值,而是直接改变 x 的值,也就是说,其本质就像字面意思那样,是在更新,而不是合并。
x = {"key1": "value1 from x", "key2": "value2 from x"}
y = {"key2": "value2 from y", "key3": "value3 from y"}
x.update(y)
x
运行结果如下:
另外也可以使用字典解包的方式来合并字典,这种方法虽然用起来很方便,很简单就达到了目的,但背后逻辑往往让人难以参透。
x = {"key1": "value1 from x", "key2": "value2 from x"}
y = {"key2": "value2 from y", "key3": "value3 from y"}
{**x,**y}
{**y,**x}
运行结果如下:
接下来,我们尝试一下 Python3.9 中新的方法,注意观察字典的先后顺序。
x = {"key1": "value1 from x", "key2": "value2 from x"}
y = {"key2": "value2 from y", "key3": "value3 from y"}
x | y
y | x
运行结果如下:
可以看到,新方法合并运算符的使用让你合并变得很方便,而且它是有返回值且不改变原来的值。我们要想像原来 update 方法那样把 y 更新到 x ,还可以使用更新运算符 |= 。
x = {"key1": "value1 from x", "key2": "value2 from x"}
y = {"key2": "value2 from y", "key3": "value3 from y"}
x |=y
x
运行结果如下:
放宽对装饰器的语法限制
在之前版本的 Python 中对于装饰器的语法是有所限制的,Python 3.9 终于将这一限制放宽任意,任何表达式都可以用在装饰器中。
之前的装饰器语法如下:
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
Python3.9 版本的装饰器语法:
decorator: '@' namedexpr_test NEWLINE
我们来简单写一个装饰器,感受一下。
首先我们写一个常规的装饰器,来实现自动将函数返回值变成大写。
def upper(func):
def wrapper(*args):
return func(*args).upper()
return wrapper
@upper
def hello(name):
return f'hello {name}'
hello('johnson')
运行结果如下:
然后来感受一下 Python3.9 的新特性,也就是什么叫任何表达式都可以?
@lambda func:(lambda *args:func(*args).upper())
def hello(name):
return f'hello {name}'
hello('johnson')
运行结果如下:
可以看到,我们直接使用 lambda 表达式就实现了装饰器,且没有单独去定义,而是随用随写。至于更多好玩的用法,大家还可以继续去探索。
新增用于移除前缀和后缀的字符串方法
增加了 str.removeprefix(prefix) 和 str.removesuffix(suffix) 用于方便地从字符串移除不需要的前缀或后缀。另外也增加了 bytes 和 bytearray 以及 collections.UserString 的对应方法,大家可以自行实验。
首先我们实验一下 str.removeprefix(prefix) 的使用:
url="https://www.psdn.icu"
url.removeprefix('https://')
运行结果如下:
然后再实验一下 str.removesuffix(suffix) 的使用:
url="https://psdn.icu/python3中的print函数/"
url.removesuffix('python3中的print函数/')
运行结果如下:
标准多项集中的类型标注泛型
在类型标注中现在你可以使用内置多项集类型例如 list 和 dict 作为通用类型而不必从 typing 导入对应的大写形式类型名 (例如 List 和 Dict)。 标准库中的其他一些类型现在同样也是通用的,例如 queue.Queue。
def greet_all(names: list[str]) -> None:
for name in names:
print("Hello", name)
__file__ 属性将是一个绝对路径
首先,我们在当前目录下新建一个 test.py
文件,然后在其中写入下面内容
#test.py
print(__file__)
然后分别尝试使用 Python3.8 和 Python3.9 去运行
python3.8 test.py
python3.9 test.py
运行结果如下:
可以看到,Python3.8 中是相对路径,而 Python3.9 成了绝对路径,很显然,绝对路径更加可靠。
datetime 模块的改进
isocalendar() 方法现在返回 namedtuple (具名元组),通过下面的例子,你将一目了然到底变化了什么。
import datetime
datetime.date.today().isocalendar()
我们先在 Python3.8 中运行上面的代码,结果如下:
然后我们在 Python3.9 中运行上面的代码,结果如下:
我们可以进一步发现具名元组的优点,那就是可以直接通过属性名访问,不止之前的索引访问。
例如如下代码:
s=datetime.date.today().isocalendar()
s[0]
s.week
s.weekday
代码运行结果如下:
math 模块的改进
math.gcd(*integers)
有时候,我们需要求几个数字的最大公约数,在 Python 中可以直接使用 math 模块的 gcd 函数。在之前的版本,gcd 函数只允许最多两个参数,这在需要求一堆数字的最大公约数的时候实在是不方便,好在 Python3.9 终于有了改进,可以使用多个参数了。
import math
math.gcd(10,15,25,55)
运行效果如下:
math.lcm(*integers)
新增了计算最小公倍数的函数 math.lcm() 。
import math
math.lcm(2,3,5)
运行效果如下:
总结
Python3.9 相较于之前的版本,主要是新增了字典的合并运算符、放宽了装饰器的语法限制、对于字符串新增了去除前缀后缀的方法、以及 math 模块和 datetime 模块的一些改进,更多的改变,大家可以查看官方文档。