Alternative to the `match = re.match(); if match: ...` idiom?
I don't think it's trivial. I don't want to have to sprinkle a redundant conditional around my code if I'm writing code like that often.
This is slightly odd, but you can do this with an iterator:
import re
def rematch(pattern, inp):
matcher = re.compile(pattern)
matches = matcher.match(inp)
if matches:
yield matches
if __name__ == '__main__':
for m in rematch("(\d+)g", "123g"):
print(m.group(1))
The odd thing is that it's using an iterator for something that isn't iterating--it's closer to a conditional, and at first glance it might look like it's going to yield multiple results for each match.
It does seem odd that a context manager can't cause its managed function to be skipped entirely; while that's not explicitly one of the use cases of "with", it seems like a natural extension.
Starting Python 3.8
, and the introduction of assignment expressions (PEP 572) (:=
operator), we can now capture the condition value re.match(r'(\d+)g', '123g')
in a variable match
in order to both check if it's not None
and then re-use it within the body of the condition:
>>> if match := re.match(r'(\d+)g', '123g'):
... print(match.group(1))
...
123
>>> if match := re.match(r'(\d+)g', 'dddf'):
... print(match.group(1))
...
>>>
I have another way of doing this, based on Glen Maynard's solution:
for match in [m for m in [re.match(pattern,key)] if m]:
print "It matched: %s" % match
Similar to Glen's solution, this itterates either 0 (if no match) or 1 (if a match) times.
No sub needed, but less tidy as a result.
Another nice syntax would be something like this:
header = re.compile('(.*?) = (.*?)$')
footer = re.compile('(.*?): (.*?)$')
if header.match(line) as m:
key, value = m.group(1,2)
elif footer.match(line) as m
key, value = m.group(1,2)
else:
key, value = None, None