I'm trying to run an example from the docs, but get the error:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: Point() accepts 0 positional sub-patterns (2 given)
Can someone explain what I doing wrong here?
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")
You need to define __match_args__
in your class. As pointed at in this section of the "What's new in 3.10" page:
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)
So your class will need to look as follows:
class Point:
__match_args__ = ("x", "y")
def __init__(self, x, y):
self.x = x
self.y = y
Alternatively, you could change your match structure to the following:
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")
(Note that you don't need a both: a class with __match_args__
defined, does not need to have its arguments specified in the match-case statements.)
For full details, I'll refer readers to PEP 634, which is the specification for structural pattern matching. The details on this particular point are in the section Class Patterns.
For a better introduction or tutorial, don't use the "What's New" documentation, as it tends to provide an overview, but may skip over some things. Instead, use PEP 636 -- Structural Pattern Matching: Tutorial, or the language reference on match statements for more details.
It is mentioned in the quoted text that a dataclass will already have an ordering, and in your example, a dataclass also works fine:
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")