如何将 mypy 推断循环变量修复为 "object"?
How to fix mypy inferring loop variable as "object"?
我做了这个简单的函数,我想用 mypy 和
皮林特。它只是解析一个字符串并将其转换为适当的
类型。
import re
from typing import Any, Callable
def parse_constant(constant: str) -> Any:
for reg, get_val in [
(re.compile(r'\'(.*)\''), str),
(re.compile(r'true', re.IGNORECASE), lambda _: True),
(re.compile(r'false', re.IGNORECASE), lambda _: False),
(re.compile(r'([0-9]+)'), int),
(re.compile(r'([0-9]+\.[0-9]+)'), float)
]:
match = reg.fullmatch(constant)
if match is not None:
if len(match.groups()) == 0:
val = None
else:
val = match.groups()[0]
return get_val(val)
return None
它工作正常但 mypy 抱怨:我得到 error: "object" not callable
在第 18 行 (return get_val(val)
).
现在,如果我将 str
替换为 lambda x: str(x)
mypy 很高兴,但 pylint
抱怨 Lambda may not be necessary
.
解决这个问题的正确方法是什么?
问题是 MyPy 必须从 Callable
和 Type
的混合中推断出 get_val
。在这种情况下, 显式注释类型以避免过于宽泛的推断。
在for
循环内,只能注解循环变量。通过把iterable移到循环外,可以注解:
import re
from typing import Any, Callable, Pattern, List, Tuple
cases: List[Tuple[Pattern[str], Callable]] = [
(re.compile(r'\'(.*)\''), str),
(re.compile(r'true', re.IGNORECASE), lambda _: True),
(re.compile(r'false', re.IGNORECASE), lambda _: False),
(re.compile(r'([0-9]+)'), int),
(re.compile(r'([0-9]+\.[0-9]+)'), float)
]
def parse_constant(constant: str) -> Any:
for reg, get_val in cases:
match = reg.fullmatch(constant)
if match is not None:
if len(match.groups()) == 0:
val = None
else:
val = match.groups()[0]
return get_val(val)
return None
将案例移到函数之外还有一个额外的好处,即它们只创建一次。这对于 re.compile
尤其重要,它现在编译一次,然后存储以供重复使用。
我做了这个简单的函数,我想用 mypy 和 皮林特。它只是解析一个字符串并将其转换为适当的 类型。
import re
from typing import Any, Callable
def parse_constant(constant: str) -> Any:
for reg, get_val in [
(re.compile(r'\'(.*)\''), str),
(re.compile(r'true', re.IGNORECASE), lambda _: True),
(re.compile(r'false', re.IGNORECASE), lambda _: False),
(re.compile(r'([0-9]+)'), int),
(re.compile(r'([0-9]+\.[0-9]+)'), float)
]:
match = reg.fullmatch(constant)
if match is not None:
if len(match.groups()) == 0:
val = None
else:
val = match.groups()[0]
return get_val(val)
return None
它工作正常但 mypy 抱怨:我得到 error: "object" not callable
在第 18 行 (return get_val(val)
).
现在,如果我将 str
替换为 lambda x: str(x)
mypy 很高兴,但 pylint
抱怨 Lambda may not be necessary
.
解决这个问题的正确方法是什么?
问题是 MyPy 必须从 Callable
和 Type
的混合中推断出 get_val
。在这种情况下,
在for
循环内,只能注解循环变量。通过把iterable移到循环外,可以注解:
import re
from typing import Any, Callable, Pattern, List, Tuple
cases: List[Tuple[Pattern[str], Callable]] = [
(re.compile(r'\'(.*)\''), str),
(re.compile(r'true', re.IGNORECASE), lambda _: True),
(re.compile(r'false', re.IGNORECASE), lambda _: False),
(re.compile(r'([0-9]+)'), int),
(re.compile(r'([0-9]+\.[0-9]+)'), float)
]
def parse_constant(constant: str) -> Any:
for reg, get_val in cases:
match = reg.fullmatch(constant)
if match is not None:
if len(match.groups()) == 0:
val = None
else:
val = match.groups()[0]
return get_val(val)
return None
将案例移到函数之外还有一个额外的好处,即它们只创建一次。这对于 re.compile
尤其重要,它现在编译一次,然后存储以供重复使用。