mypy 无法识别从超类继承的变量

Posted

技术标签:

【中文标题】mypy 无法识别从超类继承的变量【英文标题】:mypy not recognizing variables inherited from superclass 【发布时间】:2022-01-13 17:45:17 【问题描述】:

我定义了以下类:

class BackgroundThread(threading.Thread):
    def __init__(self, *args: typing.Any, **kwargs: typing.Any) -> None:
        super().__init__(*args, **kwargs)
        self._quit = threading.Event()

    def run(self) -> None:
        while not self._quit.wait(timeout=0.0):
            self._target(*self._args, **self._kwargs)

    def __enter__(self) -> None:
        self.start()
        return None

    def __exit__(self, *args: typing.Any) -> None:
        self._quit.set()
        self.join()

代码完全按预期工作。然而,mypy 抱怨说

“BackgroundThread”没有属性“_target” “BackgroundThread”没有属性“_args” “BackgroundThread”没有属性“_kwargs”

我可以通过插入来解决这个问题

class BackgroundThread(threading.Thread):
    _target: typing.Callable
    _args: typing.Tuple
    _kwargs: typing.Dict[str, typing.Any]

但是,这似乎很老套。为什么 mypy 不能识别这些来自父类的变量?是因为下划线开头吗?

【问题讨论】:

访问这些变量本身有点麻烦。我不会使用要重复的函数作为目标,而是定义一个接受函数、事件和附加参数的函数并运行循环。然后使用那个循环函数作为真正的目标。 【参考方案1】:

这是标准存根中线程的定义。下划线属性没有定义,只有 dunder 是。您可以在 Github 上请求/贡献 typeshed 以添加缺少的下划线属性。不禁止添加它们,但通常它们不会列在 typeshed stubs 中。

class Thread:
    name: str
    ident: Optional[int]
    daemon: bool
    if sys.version_info >= (3,):
        def __init__(
            self,
            group: None = ...,
            target: Optional[Callable[..., Any]] = ...,
            name: Optional[str] = ...,
            args: Iterable[Any] = ...,
            kwargs: Optional[Mapping[str, Any]] = ...,
            *,
            daemon: Optional[bool] = ...,
        ) -> None: ...
    else:
        def __init__(
            self,
            group: None = ...,
            target: Optional[Callable[..., Any]] = ...,
            name: Optional[Text] = ...,
            args: Iterable[Any] = ...,
            kwargs: Optional[Mapping[Text, Any]] = ...,
        ) -> None: ...
    def start(self) -> None: ...
    def run(self) -> None: ...
    def join(self, timeout: Optional[float] = ...) -> None: ...
    def getName(self) -> str: ...
    def setName(self, name: Text) -> None: ...
    if sys.version_info >= (3, 8):
        @property
        def native_id(self) -> Optional[int]: ...  # only available on some platforms
    def is_alive(self) -> bool: ...
    if sys.version_info < (3, 9):
        def isAlive(self) -> bool: ...
    def isDaemon(self) -> bool: ...
    def setDaemon(self, daemonic: bool) -> None: ...

【讨论】:

以上是关于mypy 无法识别从超类继承的变量的主要内容,如果未能解决你的问题,请参考以下文章

无法从超类访问 Django 模型的子类

子类是不是从超类继承私有实例变量

子类没有正确地从超类继承结构[重复]

Python子类方法从超类方法继承装饰器

Django,Python继承:从超类中排除一些字段

OWL:如何从超类继承两个类之间的属性关系?