1

我正在尝试从 docs运行一个示例,但出现错误:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: Point() accepts 0 positional sub-patterns (2 given)

有人可以解释我在这里做错了什么吗?

class Point():
    def __init__(self, x, y):
            self.x = x
            self.y = y

x, y = 5 ,5
point = Point(x, y)
match point:
    case Point(x, y) if x == y:
        print(f"Y=X at {x}")
    case Point(x, y):
        print(f"Not on the diagonal")
4

1 回答 1

4

你需要__match_args__在你的类中定义。正如“3.10 中的新增功能”页面的本节所述:

您可以将位置参数与一些为其属性提供排序的内置类(例如数据类)一起使用。您还可以通过__match_args__在类中设置特殊属性来定义模式中属性的特定位置。如果设置为 (“x”, “y”),则以下模式都是等价的(并且都将 y 属性绑定到 var 变量):

Point(1, var) 
Point(1, y=var) 
Point(x=1, y=var) 
Point(y=var, x=1)

所以你的班级需要如下所示:

class Point:                                                                                            
    __match_args__ = ("x", "y")                                                                         
    def __init__(self, x, y):                                                                           
        self.x = x                                                                                      
        self.y = y                                                                                      

或者,您可以将匹配结构更改为以下内容:

match point:                                                                                            
    case Point(x=x, y=y) if x == y:                                                                       
        print(f"Y=X at {x}")                                                                            
    case Point(x=x, y=y):                                                                                   
        print(f"Not on the diagonal")                                                                   

(请注意,您不需要两者:已__match_args__定义的类,不需要在匹配案例语句中指定其参数。)

有关详细信息,我将向读者推荐 PEP 634,它是结构模式匹配的规范。关于这一点的详细信息在Class Patterns部分中。

要获得更好的介绍或教程,请不要使用“新增功能”文档,因为它倾向于提供概述,但可能会跳过一些内容。相反,请使用PEP 636 - 结构模式匹配:教程,或match statements上的语言参考以获取更多详细信息。


在引用的文本中提到,数据类已经具有排序,在您的示例中,数据类也可以正常工作:

from dataclasses import dataclass                                                                       
                                                                                                        
@dataclass                                                                                              
class Point:                                                                                            
    x: int                                                                                              
    y: int                                                                                              
                                                                                                        
x, y = 5, 5                                                                                             
point = Point(x, y)                                                                                     
                                                                                                        
match point:                                                                                            
    case Point(x, y) if x == y:                                                                         
        print(f"Y=X at {x}")                                                                            
    case Point(x, y):                                                                                   
        print(f"Not on the diagonal")                                                                   
于 2021-10-19T09:04:29.210 回答