关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶、JS/安卓逆向等技术干货!

前几天,也就是 10 月 4 日,Python 发布了 3.10.0 版本,什么?3.9 之后居然不是 4.0?(手动狗头)其实龟叔(Guido van Rossum,吉多·范罗苏姆,Python 之父)早在去年 9 月就说了:

  1. 3.9 之后的版本为 3.10;事实上,它已经存在(在 Github Master 主分支中)。
  2. 如果有版本 4,从 3 到 4 的过渡更像从 1 到 2,而不是从 2 到 3。

相比 Python 3.9,Python 3.10 主要的新功能如下:

PEP 634 - PEP 636:结构模式匹配

在本次诸多的更新中,Structural Pattern Matching 结构模式匹配,match-case 语句无疑是最让人兴奋的功能,也就类似于 Java、C、Go 等其他语言中的 switch-case 语句,具体用法可以参考:PEP 636

来看一个简单的例子:

def http_error(status):
match status:
case 400:
print("Bad request")
case 404:
print("Not found")
case 418:
print("I'm a teapot")
case _:
print("Something's wrong with the internet") http_error(418) # I'm a teapot
http_error(500) # Something's wrong with the internet

以上代码中,最后一个 case 中的 _ 并不作为变量名,而表示一种特殊的模式,在前面的 case 中都未命中的情况下,该 case 会是最后的保障,能确保命中,它相当于 Java、C、Go 等语言中的 default 分支:

public class HttpError {
public static void main(String args[]){
int status = 500;
switch(status){
case 400:
System.out.println("Bad request");
case 404:
System.out.println("Not found");
case 418:
System.out.println("I'm a teapot");
default:
System.out.println("Something's wrong with the internet");
}
}
} // Something's wrong with the internet

match-case 语法支持可变参数 *args**rest

*args 的用法与 Python 函数中的可变参数是一个用法,允许传入多个参数:

def create_user(command):
match command.split():
case ["quit"]:
quit()
case ["create", user]:
print("create", user)
case ["create", *user]:
for u in user:
print("create", u)
case _:
print("command '{command}' not understood") create_user("create user1")
create_user("create user2 user3 user4") # create user1
# create user2
# create user3
# create user4

**rest 会匹配到字典中所有的 keyvalue

def get_dict(dic):
match dic:
case {**rest}:
print("get dict:", rest)
case _:
print("parameter not understood") get_dict({"400": "Bad request", "404": "Not found", "418": "I'm a teapot"}) # get dict: {'400': 'Bad request', '404': 'Not found', '418': "I'm a teapot"}

需要注意的是,结构模式匹配在面对不同的对象时,匹配的规则也有所不同。

当匹配对象是列表(list)或者元组(tuple)的时候,需要长度和元素值都匹配,才能命中:

def create_user(param):
match param:
case ("quit"):
quit()
case ("create", user):
print("create", user)
case ("create", *user):
for u in user:
print("create", u)
case _:
print("command '{command}' not understood") create_user(("create", "user1", "user2")) # create user1
# create user2

当匹配对象是一个字典(dict)的时候,只要 case 表达式中的 键(key)在字典对象中存在即可命中,以下示例中,很可能会认为会执行第二个 case,但实际上执行了第一个 case:

def if_action(dic):
match dic:
case {"action": action}:
print("action: %s, no object" % action)
case {"action": action, "object": _}:
print("action: %s, have object" % action) if_action({"action": "create", "object": "user1"}) # action: create, no object

当匹配对象是类对象(class)的时候,匹配的规则和字典(dict)类似,只要对象类型和对象的属性满足条件即可命中,以下示例中,很可能会认为会执行第二个 case,但实际上执行了第一个 case:

class Info:
def __init__(self, name, age):
self.name, self.age = name, age def get_info(people):
match people:
case Info(name="Bob"):
print("case 1")
case Info(name="Bob", age="20"):
print("case 2") people = Info(name="Bob", age="20")
get_info(people) # case 1

PEP 604:新型联合运算符(Union Types)

Python 是个弱类型语言,但是在 Python 3 中支持了定义传参和返回类型的写法:

def test(a: int) -> int:
return a**2

通常一个参数和返回值只能是一个类型,在 C/C++,Java,Go 等静态语言里,不可能返回两种类型,或者传参使用两种类型,但是在 Python 里可以:

def test(a: str or int) -> str or int:
return a**2

这里的 or 写法看着非常不舒服,所以在 Python 3.5 的时候引入了 typing 模块,推荐使用 Uinon 的写法:

from typing import Union

def test(a: Union[str, int]) -> Union[str, int]:
return a**2

在本次 Python 3.10.0 更新中,PEP 604 允许将联合类型(Union Types)写为 X | Y:

def test(a: str | int) -> str | int:
return a**2

新的运算符也可以用作 isinstance()issubclass() 的第二个参数:

print(isinstance(5, int | str))       # True
print(isinstance(None, int | None)) # True
print(issubclass(bool, int | float)) # True
print(isinstance(42, None | str)) # False

PEP 626:错误调试精确到行

PEP 626 中,报错提示可以精确到具体行,提示更加详细,在以前的版本中,错误消息一般会指向下一行,而不是实际错误所在的位置,现在可以指向错误代码所在的确切位置。

错误代码示例 1:

li = [1, 2, 3

之前版本报错:

  File "D:\python3Project\test.py", line 5

                 ^
SyntaxError: unexpected EOF while parsing

Python 3.10 版本报错:

  File "D:\python310Project\test.py", line 4
li = [1, 2, 3
^
SyntaxError: '[' was never closed

错误代码示例 2:

expected = {"name": "Bob", "age": 20
some_other_code = foo()

之前版本报错:

  File "D:\python3Project\test.py", line 2
some_other_code = foo()
^
SyntaxError: invalid syntax

Python 3.10 版本报错:

  File "D:\python310Project\test.py", line 1
expected = {"name": "Bob", "age": 20
^
SyntaxError: '{' was never closed

PEP 618:zip() 可选长度检查

zip() 是 Python 中的内置函数,用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

在以前的版本中,如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,示例如下:

a = [1, 2, 3]
b = [4, 5, 6]
c = [4, 5, 6, 7, 8]
zipped1 = zip(a, b)
zipped2 = zip(a, c) # 元素个数与最短的列表一致 print([z for z in zipped1]) # [(1, 4), (2, 5), (3, 6)]
print([z for z in zipped2]) # [(1, 4), (2, 5), (3, 6)]

PEP 618中,新增了 strict 参数,设置为 True 时,传入 zip() 的两个可迭代项长度必须相等,否则将抛出 ValueError

a = [1, 2, 3]
b = [4, 5, 6]
c = [4, 5, 6, 7, 8]
zipped1 = zip(a, b, strict=True)
zipped2 = zip(a, c, strict=True) print([z for z in zipped1])
print([z for z in zipped2])

报错:

[(1, 4), (2, 5), (3, 6)]
Traceback (most recent call last):
File "D:\python310Project\test.py", line 8, in <module>
print([z for z in zipped2])
File "D:\python310Project\test.py", line 8, in <listcomp>
print([z for z in zipped2])
ValueError: zip() argument 2 is longer than argument 1

BPO-12782:允许带括号的上下文管理器

Python 上下文管理器对于打开/关闭文件、处理数据库连接和很多其他事情都非常有用,在 Python 3.10.0 中,它们的语法将有一点高质量的改进,在 BPO-12782 正式允许带括号的上下文管理器,现在可以用一个 with 语句创建多行,示例如下:

with(
open("text1.txt", encoding="utf-8") as f1,
open("text2.txt", encoding="utf-8") as f2
):
print(f1.read(), f2.read())

PEP 613:显式类型别名

PEP 613 使用 TypeAlias 显式标注类型别名,提高可读性。

以前版本,可以看到,x 很容易被搞混:

x = int

def plus_int(a: x, b: x) -> x:
return a+b

Python 3.10 中,使用 TypeAlias 表明这是个别名,消除歧义:

from typing import TypeAlias

x: TypeAlias = int

def plus_int(a: x, b: x) -> x:
return a+b

性能提升

与所有最新版本的 Python 一样,Python 3.10 也带来了一些性能改进。首先是优化 str()bytes()bytearray() 构造函数,它们速度提升了 30% 左右,代码摘自 BOP-41334

$ ./python -m pyperf timeit -q --compare-to=../cpython-release2/python "str()"
Mean +- std dev: [/home/serhiy/py/cpython-release2/python] 81.9 ns +- 4.5 ns -> [/home/serhiy/py/cpython-release/python] 60.0 ns +- 1.9 ns: 1.36x faster (-27%) $ ./python -m pyperf timeit -q --compare-to=../cpython-release2/python "bytes()"
Mean +- std dev: [/home/serhiy/py/cpython-release2/python] 85.1 ns +- 2.2 ns -> [/home/serhiy/py/cpython-release/python] 60.2 ns +- 2.3 ns: 1.41x faster (-29%) $ ./python -m pyperf timeit -q --compare-to=../cpython-release2/python "bytearray()"
Mean +- std dev: [/home/serhiy/py/cpython-release2/python] 93.5 ns +- 2.1 ns -> [/home/serhiy/py/cpython-release/python] 73.1 ns +- 1.8 ns: 1.28x faster (-22%)

另一个更值得注意的优化(如果你使用类型注释)是,函数参数及其注释不再在运行时(runtime)计算,而是在编译时计算,这使得创建一个带有参数注释的函数的速度提高了大约 2 倍。

除此之外,Python 核心的各个部分还有更多的优化,你可以在 Python bug tracker 的下列问题中找到更多的细节:BPO-41718BPO-42927BPO-43452

其他改变

  • PEP 623:弃用并准备删除 PyUnicodeObject 中的 wstr 成员。
  • PEP 612:参数规范变量。
  • PEP 632:弃用 distutils 模块,推荐使用 setuptools。
  • PEP 644:CPython 的标准库仅支持 OpenSSL 1.1.1 或更新版本。
  • PEP 624:删除 Py_UNICODE 编码器 API。
  • PEP 597:添加可选的 EncodingWarning。

Python 3.10 正式发布,新增模式匹配,同事用了直呼真香!的更多相关文章

  1. 我用 Java 8 写了一段逻辑,同事直呼看不懂,你试试看。。

    业务背景 首先,业务需求是这样的,从第三方电商平台拉取所有订单,然后保存到公司自己的数据库,需要判断是否有物流信息,如果有物流信息,还需要再进行上传. 而第三方接口返回的数据是 JSON 格式的,其中 ...

  2. Python 3.10 中新的功能和变化

    随着最后一个alpha版发布,Python 3.10 的功能更改全面敲定! 现在,正是体验Python 3.10 新功能的理想时间!正如标题所言,本文将给大家分享Python 3.10中所有重要的功能 ...

  3. 利用Conda尝鲜Python 3.10

    1 简介 就在几天前,Python3.10的第一个正式版本3.10.0发布,之前我们只是从其各个测试版本中捕风捉影地知晓了一些可能加入的新特性,而在正式版本中,我们得以一睹其正式加入的诸多新特性. 本 ...

  4. 如约而至,Java 10 正式发布!

    3 月 20 日,Oracle 宣布 Java 10 正式发布. 官方已提供下载:http://www.oracle.com/technetwork/java/javase/downloads/ind ...

  5. 十. Python基础(10)--装饰器

    十. Python基础(10)--装饰器 1 ● 装饰器 A decorator is a function that take a function as an argument and retur ...

  6. 快速入门:十分钟学会PythonTutorial - Learn Python in 10 minutes

    This tutorial is available as a short ebook. The e-book features extra content from follow-up posts ...

  7. 『Python基础-10』字典

    # 『Python基础-10』字典 目录: 1.字典基本概念 2.字典键(key)的特性 3.字典的创建 4-7.字典的增删改查 8.遍历字典 1. 字典的基本概念 字典一种key - value 的 ...

  8. python进阶10 MySQL补充 编码、别名、视图、数据库修改

    python进阶10 MySQL补充    编码.别名.视图.数据库修改 一.编码问题 #MySQL级别编码 #修改位置: /etc/mysql/mysql.conf.d/mysqld.cnf def ...

  9. 如约而至,Java 10 正式发布! Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十四)Redis缓存正确的使用姿势 努力的孩子运气不会太差,跌宕的人生定当更加精彩 优先队列详解(转载)

    如约而至,Java 10 正式发布!   3 月 20 日,Oracle 宣布 Java 10 正式发布. 官方已提供下载:http://www.oracle.com/technetwork/java ...

随机推荐

  1. MySQL-Cluster 初识

          最近,对mysql-cluster进行初步了解,发现和oracle提供的RAC有一定的相似之处,但区别又很大,下面主要是mysql-cluster的搭建,至于对其的深入了解,留着以后工作需 ...

  2. uni-app 登录Abp VNexe并获取Token

    uni.request方式登录abp关键代码如下,因abp获取token需要用formdata方式请求所以需要加上请求头 const baseUrl = 'http://127.0.0.1:44323 ...

  3. 缩减Centos7xfs磁盘空间

    问题描述:df -h查看 root目录仅有20G空间,其余300G空间全在home目录下.xfs不可以直接缩减,所以只能删除xfs盘然后重新添加. 解决办法: 1. 注释想要删除的磁盘,此处以cent ...

  4. Hello Wolrd

    这是一篇测试文章.....后续会更新一些文章.

  5. 迷你商城后台管理系统---------stage3项目部署测试汇总

    系统测试 在项目部署到云服务器之前,已通过本机启动springboot程序,访问localhost:8080,输入登陆的账户等一系列操作测试:功能测试.健壮性测试,系统已满足用户规定的需求. 系统部署 ...

  6. STM32CbueIDE 体验

    STM32CbueIDE 体验 下载安装 官网下载链接:https://www.st.com/zh/development-tools/stm32cubeide.html. 软件启动时会令设置工作目录 ...

  7. PC+PLC通过Modbus协议构建工控系统

    一. 概述 工业设备采用HMI+PLC控制是比较常见的方案,随着工业自动化的要求越来越高,现在很多设备都要求接入企业MES系统,MES系统一般为WEB系统,接口形式大部分为HTTP协议,这种传统方案和 ...

  8. P1013 [NOIP1998 提高组] 进制位

    解析 看到这道题时,有没有想到搜索?然后就是一通码......然后过了. 但是,真的要用搜索吗? 我们可以观察一下.对于n进制中的数ii,如果ii加上某一个数jj会变成两位数,那么可以得到如下不等式: ...

  9. 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里打卡上班? | 百篇博客分析OpenHarmony源码 | v22.01

    百篇博客系列篇.本篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里打卡上班 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在 ...

  10. bzoj#2407-探险【最短路,二进制分组】

    正题 题目链接:https://darkbzoj.tk/problem/2407 题目大意 \(n\)个点的一张无向图(但是正反权值不同),求一个从\(1\)出发回到\(1\)且不经过重复边的最短路径 ...