03.12.19 13:53, Juancarlo Añez пише:
There are many ugly recipes about to handle the common use case that could be handled by:
def findfirst(regex, text, default=None, flags=0):
return next(finditer(regex, text, flags=flags), default=default)
Oh, this is the most strange use of finditer() that I seen! If finditer() is virtually iterative search() (with some peculiarities for zero-width matches which is irrelevant to the the first search()) why not use just search()?
Typically, the pattern for the use case will be:
m = re.search(regex, text)
if m:
matched = m.groups()
else:
matched = default
nowadays:
matched = m.groups() if (m := re.search(regex, text)) else default
The semantics of *findall()* are nicer, and so would be those of *findfirst()*.
Actually the semantic of the above code is different from the semantic of `re.findall(regex, text)[0]`. findall() yields strings if the pattern contains less than 2 capture groups and tuples if it more than 1 capture groups.
re.findall('..', 'abcd') ['ab', 'cd'] re.findall('(.).', 'abcd') ['a', 'c'] re.findall('((.).)', 'abcd') [('ab', 'a'), ('cd', 'c')]
It is not clear what behavior do you need. And I suppose that other users of findfirst() can need different behavior. search() is more powerful and allow you to get what you need. It could be easier if search() return an empty Match object instead of None if it does not find anything. However this ship is sailed, changing search() will break the code that checks `match is None`. But you can create your own Match-like object and use it to simplify expressions: matched = (m or MyMatch(default)).groups()