python3.10增加了采用模式加上相应动作的 match 语句 和 case 语句 的形式的结构化模式匹配。 模式由序列、映射、基本数据类型以及类实例构成。 模式匹配使得程序能够从复杂的数据类型中提取信息、根据数据结构实现分支,并基于不同的数据形式应用特定的动作。
语法与操作
?模式匹配的通用语法如下:
match subject:
case <pattern_1>:
<action_1>
case <pattern_2>:
<action_2>
case <pattern_3>:
<action_3>
case _:
<action_wildcard>
match?语句接受一个表达式并将其值与以一个或多个 case 语句块形式给出的一系列模式进行比较。 具体来说,模式匹配的操作如下:
?使用具有特定类型和形状的数据 (subject)?针对 subject 在 match 语句中求值?从上到下对 subject 与 case 语句中的每个模式进行比较直到确认匹配到一个模式。?执行与被确认匹配的模式相关联的动作。?如果没有确认到一个完全的匹配,则如果提供了使用通配符 _ 的最后一个 case 语句,则它将被用作已匹配模式。 如果没有确认到一个完全的匹配并且不存在使用通配符的 case 语句,则整个 match 代码块不执行任何操作。
简单模式:匹配一个字面值
让我们把这个例子看作是模式匹配的最简单形式:一个值,即主词,被匹配到几个字面值,即模式。在下面的例子中,status 是匹配语句的主词。模式是每个 case 语句,字面值代表请求状态代码。匹配后,将执行与该 case 相关的动作:
def http_error(status):
match status:
case 400:
return "请求错误!"
case 404:
return "页面不存在!"
case 418:
return "yyds!"
case _:
return "网络有点问题!"
if __name__ == '__main__':
print(http_error(500))
# point 是一个 (x, y) 元组
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")
point = (60, 60)
match point:
case (0, 0):
print("坐标原点")
case (0, y):
print(f"Y={y}")
case _:
raise ValueError("Not a point")
运行结果
Traceback (most recent call last):
File "E:\git_dfwsgroup\9first\xzProjectTeamApi\lms3_9first_com\apiInterface\web\classify.py", line 16, in <module>
raise ValueError("Not a point")
ValueError: Not a point
Process finished with exit code 1
class Point:
x: int
y: int
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")
?一个简单的例子:
class Point:
x: int
y: int
def location(point):
match point:
case Point(x=0, y=0):
print("原点是点的位置。")
case Point(x=0, y=y):
print(f"Y={y} 这个点在y轴上。")
case Point(x=x, y=0):
print(f"X={x} 这个点在x轴上。")
case Point():
print("这个点位于平面上的其他地方。")
case _:
print("不是一个点")
p = Point()
p.x = 0
p.y = 0
location((p.x, p.y))
运行结果
不是一个点
Process finished with exit code 0
?上述代码中就是把类中的属性值进行判断,当然,如果使用构造方法就会减少对象调用属性的操作:
class Point:
def __init__(self, x, y):
self.x: int = x
self.y: int = y
def location(point):
match point:
case Point(x=0, y=0):
print("原点是点的位置。")
case Point(x=0, y=y):
print(f"Y={y} 这个点在y轴上。")
case Point(x=x, y=0):
print(f"X={x} 这个点在x轴上。")
case Point():
print("这个点位于平面上的其他地方。")
case _:
print("不是一个点")
location(Point(0, 1))
运行结果
Y=1 这个点在y轴上。
Process finished with exit code 0
?您也可以使用官方提供的装饰器操作:
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
def location(point):
match point:
case Point(x=0, y=0):
print("原点是点的位置。")
case Point(x=0, y=y):
print(f"Y={y} 这个点在y轴上。")
case Point(x=x, y=0):
print(f"X={x} 这个点在x轴上。")
case Point():
print("这个点位于平面上的其他地方。")
case _:
print("不是一个点")
location(Point(0, 1))
运行结果
Y=1 这个点在y轴上。
Process finished with exit code 0
这个装饰器的作用,就是把没有构造方法(__init__)的类,添加了一个构造方法。
嵌套模式
模式可以任意地嵌套。 例如,如果我们的数据是由点组成的短列表,则它可以这样被匹配:
match points:
case []:
print("No points in the list.")
case [Point(0, 0)]:
print("The origin is the only point in the list.")
case [Point(x, y)]:
print(f"A single point {x}, {y} is in the list.")
case [Point(0, y1), Point(0, y2)]:
print(f"Two points on the Y axis at {y1}, {y2} are in the list.")
case _:
print("Something else is found in the list.")
?一个简单的例子:
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
def location(point):
match point:
case []:
print("列表上没有点。")
case [Point(0, 0)]:
print("原点是列表中唯一的点。")
case [Point(x, y)]:
print(f"单点{x}, {y}在列表中。")
case [Point(0, y1), Point(0, y2)]:
print(f"Y轴上{y1}、{y2}处的两点在列表中。")
case _:
print("在列表中找到了其他东西。")
location([Point(0, 2), Point(0, 1)])
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.")
?一个简单的例子:
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
def location(point):
match point:
case Point(x, y) if x == y:
print(f"点位于对角线上的Y=X {x}处。")
case Point(x, y):
print("点不在对角线上。")
location(Point(1, 1))