1

The official tutorial (https://www.python.org/dev/peps/pep-0636/#adding-a-ui-matching-objects) shows that you can use use objects with the new pattern matching syntax, so I wanted to use it with regex matches like this:

import re

match re.match(r"^foo", "foobar"):
    case re.Match(span=(start, end), match=match):
        print(f"match: {match} ({start}-{end})")
    case _:
        print("no matches")

But the first case never executes, what am I doing wrong?

5
  • Well, I played a while with it. I suppose the problem is result of the following: first, you can't create re.Match instances (re.Match(span=(0,3), match='foo') ` Traceback (most recent call last): ` ` File "<stdin>", line 1, in <module> ` TypeError: cannot create 're.Match' instances), so they don't have ordinary __init__. Second, they don't define __match_args__ explicitly. Unfortunately, re is c-module, so we can't examine direct python equivalent. Commented Jan 5, 2022 at 21:46
  • As far as I can see, re.Match doesn't define __match_args__ which is required for the new match statement. Commented Jan 5, 2022 at 21:52
  • @md2perpe It isn't required! Try to define simple class without it and match against it. class Car: def __init__(self, a=1): self.a = a. Car instance will match properly. match Car(3): case Car(a=a): print(a) prints 3. Commented Jan 5, 2022 at 21:54
  • According to the specification ("If only keywords are present /.../"), the object matched must have all the attributes named by the keywords. A Match object has no match attribute. Commented Jan 5, 2022 at 22:07
  • A thing that I realized is that span and match in re.Match instances are methods not attributes for some reason despite what the pretty-printed instance suggests. So I guess it really is not possible to directly use it with match statements without doing extra work. Commented Jan 6, 2022 at 12:25

1 Answer 1

0

Use a wrapper to wrap the args you want, or even if you just want a non-none match, you can do that here.

 import re


class MatchWrap:
    __match_args__ = "string"

    def __init__(self, string, match: None):
        self.string = string
        self.match = match


def wrap_match(match):
    if match:
        return MatchWrap(match.string, match)
    else:
        return None


match wrap_match(re.match(r"^foo", "foobar")):
    case MatchWrap(string="foobar") as obj:
        print(f"match: {obj.match.string} ({obj.match.start()}-{obj.match.end()})")
    case _:
        print("no matches")
Sign up to request clarification or add additional context in comments.

1 Comment

This works, but I was hoping that pattern matching can deal with match objects in a slightly cleaner and simpler way, but making wrapper classes isn't exactly what I wished for. But this answers the question, so I'll accept this answer for now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.