看完 Python3.10 的新特性,我决定仍不更新

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 是变量名称
    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 之禅的初心。

如果觉得有收获,欢迎点赞,留言,在看和关注,今天的分享就到这里,感谢阅读。

留言讨论