Point() 接受 0 个位置子模式(给定 2 个)

Point() accepts 0 positional sub-patterns (2 given)

我正在尝试 运行 一个示例 from the 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")

您需要在 class 中定义 __match_args__。正如“3.10 中的新增功能”页面的 in this section 所指出的:

You can use positional parameters with some builtin classes that provide an ordering for their attributes (e.g. dataclasses). You can also define a specific position for attributes in patterns by setting the __match_args__ special attribute in your classes. If it’s set to (“x”, “y”), the following patterns are all equivalent (and all bind the y attribute to the var variable):

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

因此您的 class 需要如下所示:

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__ 的 class,不需要在 match-case 语句中指定其参数。)

有关完整的详细信息,我建议读者参阅 PEP 634, which is the specification for structural pattern matching. The details on this particular point are in the section Class Patterns

为了获得更好的介绍或教程,请勿使用“新增功能”文档,因为它往往会提供概述,但可能会跳过某些内容。相反,请使用 PEP 636 -- Structural Pattern Matching: Tutorial, or the language reference on match statements 获取更多详细信息。


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

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")