As @2e0byo says in their answer, the issue here is that, in general, re.match could return a Match object, or it could return None, and Mypy is warning you about that.
If you know (for some reason) that this pattern will always match, you could silence Mypy by adding a cast (docs here):
import re
from typing import cast
x = [
"info_2_mation_1_thing",
"info_2_mation_5_thing",
"info_2_mation_2_thing",
"info_2_mation_3_thing",
"info_2_mation_13_thing",
"info_2_mation_4_thing",
]
result = sorted(
x,
key=lambda x: int(cast(re.Match[str], re.match(r"info_\d_mation_(\d+)_thing", x)).group(1))
)
Or, you could silence MyPy by adding a # type: ignore comment. (It's best to only silence specific mypy errors for a certain line, rather than silencing all mypy errors for a certain line. This is the same as the principle that you should never use a bare except in a try/except block. You can find out the specific kind of error Mypy is raising by using the --show-error-codes option. In this case it's the [union-attr] code, so we silence only those specific errors using # type: ignore[union-attr].)
import re
x = [
"info_2_mation_1_thing",
"info_2_mation_5_thing",
"info_2_mation_2_thing",
"info_2_mation_3_thing",
"info_2_mation_13_thing",
"info_2_mation_4_thing",
]
result = sorted(
x,
key=lambda x: int(re.match(r"info_\d_mation_(\d+)_thing", x).group(1)) # type: ignore[union-attr]
)
If you do not know that the pattern will always match, then Mypy is raising a valid error. In this case, in order to satisfy MyPy, you'll need to introduce some kind of test checking that the result of re.match is not None. Since Match objects are always truthy, it is here safe and idiomatic to test the truthiness of the returned value from re.match, even though normally we would test for the presence of None using is. In this snippet, I've used the walrus operator, which was introduced in Python 3.8:
import re
x = [
"info_2_mation_1_thing",
"info_2_mation_5_thing",
"info_2_mation_2_thing",
"info_2_mation_3_thing",
"info_2_mation_13_thing",
"info_2_mation_4_thing",
]
DEFAULT = -1
result = sorted(
x,
key=lambda x: int(m.group(1)) if (m := re.match(r"info_\d_mation_(\d+)_thing", x)) else DEFAULT
)
All three of these solutions result in rather long lambda functions. One way of abbreviating these functions (and making your code slightly more efficient as a happy side-effect) would be to pre-compile your regex patterns. The third solution I gave above would be refactored as this:
import re
x = [
"info_2_mation_1_thing",
"info_2_mation_5_thing",
"info_2_mation_2_thing",
"info_2_mation_3_thing",
"info_2_mation_13_thing",
"info_2_mation_4_thing",
]
DEFAULT = -1
PATTERN = re.compile(r"info_\d_mation_(\d+)_thing")
result = sorted(
x,
key=lambda x: int(m.group(1)) if (m := PATTERN.match(x)) else DEFAULT
)