Python3.10 在 2021 年的 10 月 3 号发布,目前已经过去 1 个月了,关于它的新特性相信大家已经有所耳闻,不过我决定仍然不更新,目前我在用的版本是 Python3.8,没有任何不爽。下面说一说我不更新的理由。

第一、相关的库可能还未跟进

如果你更新到了最新版本,已有的代码能否在不修改的情况下仍然可以正常运行?是首先要考虑的问题。

Python 的第三方库都是基于开源志愿者的劳动,他们免费做着非常有价值的工作,而且适配新的 Python 版本都需要时间。此外,由于升级涉及许多不同的群体,协调和发布需要更多时间。

第二、很多新特性没使用价值

盘点一下 Python3.10 的那些没什么用的新特性(个人观点,可以留言来喷):

1、with 可以加括号了

比如:

with (     CtxManager1() as example1,     CtxManager2() as example2,     CtxManager3() as example3, ):     ...

这一点,我基本用不到,也不清楚什么样的情况需要这样写。要是有多个上下文,我就串着多写几个就是了,要是 example1 和 example2 有关系,我可以嵌套:

with CtxManager1() as example1:     with CtxManager2() as example2:         ...     ...

这样写不是层次更清晰吗?

2、match case 就是花花肠子

Python3.10 新增了 match 和 case 软关键字。什么是软关键字?就是虽然是关键字,但是可以作为变量名,虽然如此,你肯定也不愿意让 match 成为你的变量名了,因为这样也是不会报错的:

match match: #后一个 match 是变量名称

match match: #后一个 match 是变量名称     case case:         <action>

3.10 的 match case 的语法如下:

match subject:     case <pattern_1>:         <action_1>     case <pattern_2>:         <action_2>     case <pattern_3>:         <action_3>     case _:         <action_wildcard>

它的用法可多了,有些我都快看不懂了。比如先来个简单的:

def match_errno(errno):     match errno:         case 0:             pass         case 1:             pass         case 42:             print("42!")         case _:             print("wildcard")

这里有个 _ 表示谁也不匹配的情况,相当于一个默认值,但是 _ 本来是用来表示一个后续不再使用的变量的,假如这样调用,虽然解释的通,总感觉怪怪的:

>>> _ = 42 >>> match_errno(_) 42!

再来个复杂一点的:

def command_split(command):     match command.split():         case ["make"]:             print("default make")         case ["make", cmd]:             print(f"make command found: {cmd}")         case ["restart"]:             print("restarting")         case ["rm", *files]:             print(f"deleting files: {files}")         case _:             print("didn't match")

我乍一看觉得这代码有问题,cmd 和 files 是未定义的变量啊,却可以用在 case 的表达式里面,实际运行却是没问题的:

command_split("make") command_split("make clean") command_split("restart") command_split("rm a b c")  # default make # make command found: clean # restarting # deleting files: ['a', 'b', 'c']

匹配后剩余的部分可以变成一个变量,不得不服还可以这样用。

再看一个:

def match_capture_subpattern(command):     match command.split():         case ["go", ("north" | "south" | "east" | "west") as direction]:             print(f"going {direction}")

你看还能结合 as 使用。牛逼不牛逼?

最后再看一个:

match point:     case Point(x, y) if x == y:         print(f"The point is located on the diagonal Y=X at {x}.")     case Point(x, y):         print(f"Point is not on the diagonal.")

case 里面还可以再用 if,牛逼不牛逼?

这些花样招式,除了增加程序员的心智负担,能有啥好处?我简简单单的 if elif 就搞定了,可读性还高。再说了这 match 并性能上的提升,甚至有时候还更慢,何苦呢?

Python 为什么一开始就没有 match,现在都 2021 年了,你新增个 match,是忘了初心吗?

3、新的类型提示,笑死我了

Python3.9 这样写的:

from typing import Union a: Union[int, str] = 1

Python3.10 可以这样写:

a: str | int = 1

讲真,即使你换成 |,我也不大可能会用。类型提示是学习人家静态语言的优势,提示程序的可读性和可维护性,修改代码时别传错了变量类型。

何况 Python 解释器根本不检查类型提示是否有错误,纯属自娱自乐:

>>> def fun(x :int) -> str: ...     return x ... >>> print(fun('asf')) asf >>>

如果一个变量可以有很多类型,还提示个屁啊?提示的多了,还不如不提示,本来就是动态语言嘛。自己玩自己,搞笑吧,哈哈哈哈。

我用类型提示最多就用一个类型,要是超过一个类型,我就不提示。或者自己修改代码,用得着那么多类型么?

第三、还不是很稳

Python 3.9.0 于 2020 年 10 月发布。3.9.1 于 2 个月后发布,其中包含一长串错误修正。同样的,Python3.10.x 也可能会有一些错误修正,让它再飞一会儿。

Python 3.10 有了新的语法:match-case,但是一些格式化工具或 IDE 可能还不支持。即使支持,你需要升级他们。

总之 Python3.10.0 才一个月,还不是很稳。

那你可能会问了,什么时候算稳?

我觉得比最新版本低 1-2 个是最好的选择,比如 Python3.10 发布了,那么可以考虑升级到 Python3.8 或 Python3.9,因为此时这些版本已经足够稳定。

另一方面,除非你用的版本宣告了不支持安全更新的时间,或者报告了 bug,否则,你可以一直不更新。比如说,Python 3.6 将在 2021 年 12 月结束安全更新,此时应该升级到 Python3.7 或以后的版本。

最后的话

基于以上三点,我决定不会更新 Python3.10。当然,Python3.10 也有比较好的新特性,比如更友好的报错提示,当你的括号、引号未闭合时,会抛出更加清晰明了的错误。

很喜欢 Python 之禅的那两句:简单胜过复杂,明确优于隐晦。希望 Python 的更新也能保持 Python 之禅的初心。