如何告知mypy某一条件已得到保证?附代码报错场景
解决mypy返回值类型不匹配的问题
这个问题很典型——你已经通过assert len(numbers) > 0确保了输入列表非空,循环一定会执行至少一次,所以largest_numbers绝对不会是None,但mypy没办法自动识别这个运行时约束。下面有几种靠谱的解决方式:
方法1:在return前添加断言,让mypy明确变量非None
在return语句之前加一句assert largest_numbers is not None,mypy会理解到这个断言之后,largest_numbers的类型就不再是Optional[List[int]]了:
from typing import List def find_largest(numbers: List[int]) -> List[int]: """ >>> find_largest([3, 4, 5, 5, 3, 1, -2, 4, 3, 3]) [5, 5] """ assert len(numbers) > 0 # guaranteed by caller largest_numbers = None value = None for number in numbers: if value is None or number > value: largest_numbers = [number] value = number elif number == value: largest_numbers.append(number) assert largest_numbers is not None # 告诉mypy这个变量不可能是None return largest_numbers
这个方法的好处是不需要大改代码逻辑,只是加一句断言,既增强了代码的健壮性(如果 caller 违反约定传入空列表,会直接抛出断言错误),又让mypy能正确推断类型。
方法2:调整初始化逻辑,避免用None初始化
既然输入列表非空,我们可以直接用第一个元素初始化value和largest_numbers,然后从第二个元素开始遍历。这样变量从一开始就是List[int]类型,mypy自然不会报错:
from typing import List def find_largest(numbers: List[int]) -> List[int]: """ >>> find_largest([3, 4, 5, 5, 3, 1, -2, 4, 3, 3]) [5, 5] """ assert len(numbers) > 0 # guaranteed by caller value = numbers[0] largest_numbers = [value] for number in numbers[1:]: if number > value: largest_numbers = [number] value = number elif number == value: largest_numbers.append(number) return largest_numbers
这种方式更符合类型安全的最佳实践,变量的类型从一开始就明确,不需要额外的断言或类型转换。
方法3:使用typing.cast强制转换类型
如果你不想改代码结构,也可以用cast告诉mypy:“我保证这个变量此时是List[int]类型”:
from typing import List, cast def find_largest(numbers: List[int]) -> List[int]: """ >>> find_largest([3, 4, 5, 5, 3, 1, -2, 4, 3, 3]) [5, 5] """ assert len(numbers) > 0 # guaranteed by caller largest_numbers = None value = None for number in numbers: if value is None or number > value: largest_numbers = [number] value = number elif number == value: largest_numbers.append(number) return cast(List[int], largest_numbers)
不过要注意,cast只是给mypy的提示,不会做运行时检查,所以只有当你100%确定变量不会是None的时候才用,否则可能隐藏bug。
个人更推荐方法1或方法2,方法1对现有代码改动最小,方法2的代码更清晰且类型更安全。
内容的提问来源于stack exchange,提问作者Martin Thoma
相关产品推荐
相关产品推荐

