正如@2e0byo 在their answer 中所说,这里的问题是,一般来说,re.match 可能会返回 Match 对象,或者它可能会返回 None,而 Mypy 会就此向您发出警告。
如果您知道(出于某种原因)此模式将始终匹配,您可以通过添加 cast(文档 here)来使 Mypy 静音:
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))
)
或者,您可以通过添加 # type: ignore 评论使 MyPy 静音。 (最好只为某一行静默特定的 mypy 错误,而不是静默某一行的所有 mypy 错误。这与您永远不应在 try/@987654332 中使用裸 except 的原则相同@ 块。您可以使用 --show-error-codes 选项找出 Mypy 引发的特定类型的错误。在这种情况下,它是 [union-attr] 代码,因此我们使用 # 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]
)
如果您不知道该模式将始终匹配,那么 Mypy 将引发一个有效错误。在这种情况下,为了满足 MyPy,您需要引入某种测试检查 re.match 的结果不是 None。由于Match 对象总是真实的,因此在这里测试来自re.match 的返回值的真实性是安全且惯用的,即使通常我们会使用is 测试None 的存在。在这个 sn-p 中,我使用了 Python 3.8 中引入的walrus operator:
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
)
所有这三个解决方案都会导致相当长的lambda 函数。缩写这些函数的一种方法(并使您的代码稍微更有效作为一个愉快的副作用)是预编译您的正则表达式模式。我上面给出的第三个解决方案将被重构为:
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
)