结构模式匹配
介绍
Deadsnakes软件源的安装
Python3.10的安装
结构模式匹配 和 | (逻辑or操作符)
元组(turple)
类(class)
if 子句模式
复杂模式和通配符
总结
更好的错误信息
简介
语法错误(SyntaxErrors)
缩进错误(IndentationErrors)
属性错误(AttributeErrors)
命名错误(NameErrors)
总结
与类型提示相关的新功能
简介
Union 操作符(Union Operator)
类型别名(Type Aliases)
总结
其他新功能
介绍
带括号的上下文管理器
向 zip 添加可选的长度检查
字典视图映射
为整数添加一个有效的 popcount 计算方法
总结
很多编程语言都有 switch/case 语句,很多人也曾吐槽 Python 在这方面的缺失,Python3.10 终于引入了这一语法,由 match 关键词和 case 语句组成。通用语法如下:
match subject:
case
case
case
case _:
知识点
日常开发/部署操作中我们经常会遇到安装Python的需求,然而有的时候Ubuntu自带的软件源中的Python版本并不能满足我们在程序中使用一些较新特性的需求。这时除了自行编译Python之外,我们还有另外一种选择,那就是使用一个由第三方维护的PPA软件源来方便的安装所需要的Python版本。
在这里我们使用的环境是Linux,在Linux终端中输入以下命令来安装Deadsnakes
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get update
之后根据提示按下回车键,就会自动安装完成。
PS:如果提示add-apt-repository命令不存在的话,不妨安装 software-properties-common 这个软件包。
典型用法:
sudo apt-get install python3.7
python3.7 --version
python3.7 -m pip install virtualenv
然后就可以安装Python3.10 了
sudo apt install python3.10-full
顺便给 Python3.10 安装 pip ,方便安装需要的模块
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" && python3.10 get-pip.py
安装之后我们可以进入 Python3.10 交互环境
python3.10
运行效果如下:
我们先写一个简单的示例:
def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case 455 | 456:
return "This is a custom error"
case _:
return "Something's wrong with the Internet"
http_error(418)
http_error(455)
http_error(456)
http_error(499)
运行效果如下:
可以看到,如果能匹配到,就返回对应的语句,否则就返回最后一行的通配语句。当然,统配语句也可以省略,省略相当于返回 None.
另外,case 455 | 456: 这行语句中的 | (逻辑or操作符)可以组合多个选项。
当然,Python3 的 match-case 可不仅是上面这些简单的用法。
point=(5,6)
match point:
case (0, 0):
print("Origin")
case (0, y):
print(f"Y={y}")
case (x, 0):
print(f"X={x}")
case (x, y):
print(f"X={x}, Y={y}")
case _:
raise ValueError("Not a point")
运行效果如下:
class Point():
def __init__(self,x,y):
self.x = x
self.y = y
def location(point):
match point:
case Point(x=0, y=0):
print("Origin is the point's location.")
case Point(x=0, y=y):
print(f"Y={y} and the point is on the y-axis.")
case Point(x=x, y=0):
print(f"X={x} and the point is on the x-axis.")
case Point():
print("The point is located somewhere else on the plane.")
case _:
print("Not a point")
point = Point(0, 1)
location(point)
运行效果如下:
我们可以 if 在模式中添加一个子句,称为 “Guard”(警卫、守卫 的意思)。如果 Guard 是错误的,match 则继续尝试下一个 case 块。
我们先写一个例子:
point = Point(x=0,y=0)
match point:
case Point(x=x, y=y) if x == y:
print(f"The point is located on the diagonal Y=X at {x}.")
case Point(x=x, y=y):
print(f"Point is not on the diagonal.")
运行效果如下:
下面是一个复杂模式的例子,我们先来看看代码:
def func(person):
match person:
case (name,"teacher"):
print(f"{name} is a teacher.")
case (name, _, "male"):
print(f"{name} is man.")
case (name, _, "female"):
print(f"{name} is woman.")
case (name, age, gender):
print(f"{name} is {age} old.")
func(("Sam", "teacher"))
func(("John", 25, "male"))
func(("John", 25, "man"))
func(["John", 25, "female"])
运行效果如下:
可以看到,我们在调用时有两个参数的方式、三个参数的方式,限定参数内容的方式和不限定参数的方式,甚至通配的方式,函数都能够畅快的运行。
我们在示例中有使用了元组方式和列表方式作为参数,但其实我们可以使用任何可迭代对象。
Python3.10 终于引入了 switch 语法,由 match 关键词和 case 语句组成。本站章节与大家一起学习了常见的一些使用方法,相信还有更多好玩的使用方式,大家可以大胆尝试。
Python3.10 对错误信息进行了优化,我们主要将关注语法错误、缩进错误、属性错误、命名错误,我们分别举几个例子,让大家了解 Python3.10 的进步。
知识点
字典未关闭
当解析包含未关闭的括号或方括号的代码时,解释器现在将提醒未关闭括号的位置。
我们新建一个 example.py 文件,写入下面的代码:
#example.py
expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
38: 4, 39: 4, 45: 5, 46: 5, 47: 5, 48: 5, 49: 5, 54: 6,
大家应该注意到了,我们故意没有在字典右侧加上括号去关闭它。
首先,我们在终端中用 Python3.8 运行这个文件,系统已安装 python3.8,可以直接运行。
运行效果如下:
可以看到,Python3.8 的错误信息不够明确。
然后我们使用 Python3.10 运行这个文件:
python3.10 example.py
运行效果如下:
可以看到,Python3.10 直接提醒我们没有关闭字典。
缺号冒号
如果我们在运行代码时缺少选择结构的冒号,就会报错。
if 5>3
我们首先在 Python3.8 中运行我们的代码,运行效果如下:
可以看到,Python3.8 的错误信息不够明确。
然后在 Python3.10 中运行我们的代码:
可以看到,Python3.10 中会提醒我们缺少冒号。
在本该用 == 进行比较时错用 =
'5' = 5
用 Python3.8 运行效果如下:
可以看到,Python3.8 的错误信息不够明确。
用 Python3.10 运行效果如下:
可以看到,Python3.10 提醒我们使用 == 替换 =
Python3.10 对缩进错误也进行了更好的捕捉反馈
def foo():
if 5>3:
print('yes')
Python3.8 运行效果如下:
可以看到,Python3.8 已经有不错的错误提醒
Python3.10 运行效果如下:
可以看到,Python3.10 提醒我们缩进问题时会有更多信息。
在 Python3.10 中,我们使用方法属性错误时,解释器会猜测我们其实想要使用的是什么,并做出提醒,比如我们故意把列表的 append 方法写成 appendd,运行效果如下:
在 Python3.10 中,我们引用变量名错误时,解释器也会做出提醒。
website_name = 'lanqiao'
website_nome #故意写错一个字母
运行效果如下:
Python3.10 对错误信息进行了优化,在语法错误、缩进错误、属性错误、命名错误等多个方面都进行了优化,错误信息能够帮助我们更好的调试代码,更快的修复 bug。
类型提示又叫类型声明、类型标注、类型注释,从 Python3.5 开始正式引入 typing 模块,从 Python3.6 开始已经获得全面的类型声明的支持,当然这一支持也在不断的进步,本节将介绍在 Python3.10 中关于类型提示方面的主要变化。
知识点
在以前的 Python 版本中,要想添加多种类型参数提醒,需要使用 typing.Union 方法:
from typing import Union
def square(number: Union[int, float]) -> Union[int, float]:
return number ** 2
现在可以以更简洁的方式编写类型提示:
def square(number: int | float) -> int | float:
return number ** 2
这种用法在 isinstance 函数中也可以使用
isinstance(1, int | str)
运行效果如下:
在 Python 的早期版本中,增加了类型别名,以允许我们创建表示用户定义类型的别名。
MyType = str
def foo(something: MyType) -> MyType:
return something
在 Python3.10 中,类型别名的语法将改为:
from typing import TypeAlias
MyType: TypeAlias = str
def foo(something: MyType) -> MyType:
return something
在复杂的代码库中,类型提示往往可以极大地提高可读性。当然,并不是每个开发者都想使用类型注释,因此 Python 这种动态语言将其设计为可选的功能。当然,越来越多的开发者已经开始大规模使用类型提示。本章节主要介绍了 Python3.10 中新增的 Union 操作符和类型别名。
Python3.10 还增加了很多新功能以及内置模块的更新、优化,下面再简单介绍几个有趣的改进。
知识点
Python 上下文管理器在打开/关闭文件、处理数据库连接和很多其他事情都非常有用,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源。
在 Python3.10 中,允许带圆括号的上下文管理器在多行中进行,如果你想用一个 with 语句创建多行,这是很方便的,下面是一个简单的例子:
with (
open("file1.txt",'w') as f1,
open("file2.txt",'w') as f2,
):
f1.write('hello file1')
f2.write('hello file2')
运行效果如下:
默认情况下,zip 函数在最短的迭代次数用尽时停止。它将忽略较长的可迭代项中的其余项,从而将结果缩短为最短的可迭代项的长度,例如下面的代码:
list(zip(range(3), ['fee', 'fi', 'fo', 'fum']))
运行效果如下:
Python3.10 引入了 PEP 618,也就是让 zip 函数现在具有一个可选的长度检查 strict 参数,默认情况下strict = False,可省略。
如果希望可迭代项只在长度相等的情况下使用的话,那就建议使用该 strict=True 选项,如果可迭代项长度相等的情况下会和默认情况下效果相同。
list(zip(('a', 'b', 'c'), (1, 2, 3))) #默认情况
list(zip(('a', 'b', 'c'), (1, 2, 3), strict=True)) #加入strict参数
运行效果如下:
如果可迭代项长度不相等,则会引发 ValueError 。
list(zip(range(3), ['fee', 'fi', 'fo', 'fum'], strict=True))
运行效果如下:
如果没有 strict=True 参数,则导致可迭代项长度不相等的任何错误都将被忽略,可能在程序的另一部分中表现为难以发现的错误。
字典的三个方法 dict.keys()、dict.values() 和 dict.items() 会返回不同的视图,现在都增加了 mapping 属性,可以返回原始字典。
data={'python':2021,'java':2020}
k=data.keys()
print(k)
print(k.mapping)
运行效果如下:
大家可以自行测试 dict.values() 和 dict.items() 的 mapping 属性,效果一样。
汉明重量是一串符号中非零符号的个数,是以理查德·卫斯里·汉明的名字命名的,它在包括信息论、编码理论、密码学等多个领域都有应用。
在密码学以及其它应用中经常需要计算数据位中 1 的个数,针对如何高效地实现人们已经广泛地进行了研究。
Python3.10 为整数类型增加了一个新方法 int.bit_count() 可以返回给定整数的二进制位中 1 的个数。
我们可以参考 bin 函数来进行理解,代码如下:
a = 10
bin(a) #a的二进制表示
a.bit_count()
运行效果如下:
再来一个例子:
b=255
bin(b) #b的二进制表示
b.bit_count()
运行效果如下:
本章节介绍了带括号的上下文管理器、zip 新添加的 strict 参数、字典新的映射方法、以及 popcount 算法的整数 bit_count 属性,大家可以继续探索 Python3.10 的更多的变化。