Python中的模式匹配

2020-10-20 22:41:15

此回购包含问题跟踪器、示例和与PEP 622相关的早期工作:结构模式匹配。PEP本身的更新应在PEPS回购中进行。

Brandt Bucher编写的完整参考实现可以作为CPython repo的分支获得。这很容易转换为Pull请求。

对于那些不愿从源代码构建CPython二进制文件的人,请单击本自述文件顶部的按钮。

Match语句接受表达式,并将其与作为一个或多个CASE块给定的后继字符进行比较。表面上看,这类似于C、Java或JavaScript(许多其他语言)中的switch语句,但功能要强大得多。

Def http_error(Status):匹配状态:案例400:返回";错误请求";案例401:返回";未经授权";案例403:返回";禁止";案例404:返回";未找到";案例418:返回";i';m茶壶";案例_:返回";其他";

注意最后一块:";变量名";_充当通配符,从不会失败。

#主题为(x,y)元组匹配点: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_:提高值错误(";不是点";)。

仔细研究一下那个!第一个模式有两个文字,可以认为是上面显示的文字模式的扩展。但是接下来的两个模式结合了一个文字和一个变量,变量从主题(点)捕获一个值。第四个模式捕获两个值,这使得它在概念上类似于解包赋值(x,y)=point。

如果使用类来组织数据(例如,数据类),则可以使用类名后跟类似于构造函数的参数列表,但具有捕获变量的功能:

从数据类导入DataClass@DataClass类Point:x:int y:int def Where is(Point):Match Point:Case Point(0,0):Print(";Origin";)Case Point(0,y):Print(f";Y={y}";)Case Point(x,0):Print(f";X={x}";)Case Point():打印(";其他";)case_:打印(";不是点";)。

我们也可以使用关键字参数。以下模式等价(并且都将y属性绑定到var变量):

模式可以任意嵌套。例如,如果我们有一个入围的点列表,我们可以这样匹配它:

Match Points:case[]:Print(";No Points";)case[Point(0,0)]:Print(";the Origin";)case[Point(x,y)]:Print(f";Single Point{x},{y}&34;)case[Point(0,y1),Point(0,y2)]:Print(f";Y轴上{y1},{y2}";)两个案例_:打印(";其他";)。

我们可以在模式中添加IF子句,称为守卫。如果Guard为false,则Match继续尝试下一个CASE块。请注意,值捕获发生在评估保护之前:

匹配点:案例点(x,y),如果x==y:打印(f";Y=X at{x}";)案例点(x,y):打印(f";不在对角线";)。

与解包赋值一样,元组和列表模式具有完全相同的含义,实际上匹配任意序列。一个重要的例外是它们不匹配迭代器或字符串。(从技术上讲,主题必须是集合的实例。abc.Sequence)。

序列模式支持通配符:[x,y,*rest]和(x,y,*rest)的工作方式类似于解包赋值中的通配符。*之后的名称也可以是_,因此(x,y,*_)匹配至少两个项的序列,而不绑定其余项。

映射模式:{";带宽";:b,";延迟";:l}从DICT捕获";带宽";和";延迟";值。与Sequencepatterns不同,额外的键被忽略。还支持通配符**REST。(但是**_会是多余的,所以不允许。)。

模式可以使用命名常量。这些名称必须用点分隔,以防止它们被解释为捕获变量:

从枚举导入枚举类颜色(枚举):红色=0绿色=1蓝色=2匹配颜色:案例颜色。红色:打印(";我看到红色!";)表壳颜色。绿色:打印(草为绿色)表壳颜色。蓝色:印花(#34;I&39;I&I‘我感觉到了忧郁:(";)。

字面值None、False和True被特殊处理:与主题的比较是使用is完成的。这是:

类可以通过设置类变量__MATCH_ARGS__来覆盖从位置参数到属性的映射。请参阅PEP中的相关内容。