首页 > 解决方案 > 如何使用 None 作为非可选变量的占位符而不让 mypy 抱怨它?

问题描述

直接上代码:

from typing import Optional, List


class Bar:
    pass


class Foo:
    def __init__(self, bar_list: List[Optional[Bar]]) -> None:
        self.bar_list: List[Bar] = bar_list # mypy will signal an error here

        for i, bar in enumerate(self.bar_list):
            if bar is None:
                self.bar_list[i] = self.__default_bar()

    def __default_bar(self):
        # create default
        pass

mypy 这样做是非常有意义的,但是我想明确一点,在使用此类时foo.barl_list不应该期望有None元素,同时还提供了只分配一些自定义值并让构造函数为其余部分添加默认值的灵活性。

那么如何在不触发 mypy 错误的情况下保留此功能呢?一种方法是初始化self.bar_list为一个空列表,然后附加所有值,但这会导致列表重新分配成本在大列表的情况下可能很重要,所以我正在寻找替代方案。

标签: pythonpython-3.xmypy

解决方案


您正在尝试做的事情从根本上与静态类型的List[Bar]. 但是,您可以通过将列表转换为不同的类型来告诉静态类型检查器您知道自己在做什么。您可以通过确实将每个替换NoneBar. (需要明确的是,类型检查器无法帮助您验证您确实这样做了。)

def __init__(self, bar_list: List[Optional[Bar]]) -> None:
    self.bar_list: List[Bar] = typing.cast(List[Bar], bar_list)

    for i, bar in enumerate(self.bar_list):
        if bar is None:
            self.bar_list[i] = self.__default_bar()

推荐阅读