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 之禅的初心。