如何为类键入注释装饰器?

2024-09-27 00:11:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下代码:

class Mixin:
    def foo(self) -> int:
        return 1

def add_mixin(cls):
    class WithMixin(cls, Mixin):
        __name__ = cls.__name__
        __doc__ = cls.__doc__
    return WithMixin

@add_mixin
class B:
    def bar(self) -> int:
        return 2

b = B()
print(b.foo())
print(b.bar())

我知道,在这个特殊的例子中,我可以只写B(Mixin)而不使用装饰器,但实际上add_mixin中有很多逻辑,它选择/定制Mixin类(想想@dataclass

代码按照您期望的方式工作:打印1和2。然而,它使我的pyright失明-我不再能够跳到bar,因为pyright不理解WithMixin同时从MixinB继承

此外,mypy会以另一种方式感到困惑:

mypy type_checking.py
type_checking.py:17: error: "B" has no attribute "foo"
Found 1 error in 1 file (checked 1 source file)

我正在注释一个现有库的核心,因此@overloads列表或一些直接的魔法对我来说是好的-我只希望注释是正确的

我想在两件事上得到一些帮助:

  1. 我如何正确地注释add_mixin(或者重写它以获得相同的效果),以便pyright/mypy正常工作
  2. 有关于打字的综合资源吗?最好是解释typing模块的实现(这很混乱!)以及类型检查器使用这些注释的方式。我读过reference for typing,也读过PEP 483PEP 484,我想我对所有协方差/反方差/绑定类型的东西都有相当好的理解。然而,当有一件我以前没见过的复杂的事情发生时(比如这里),我感到完全迷失了方向。谷歌搜索通常会得到相同的参考风格或表面文章(或政治公众人物)

我经历了多次失败的尝试,最后一次是:

from typing import *

class Mixin:
    def foo(self) -> int:
        return 1

_T1 = TypeVar("_T1")
class WithMixin(Type[_T1], Mixin):
    ...


def add_mixin(cls: Type[_T1]) -> WithMixin[_T1]:
    return type(cls.__name__, (cls, Mixin), {})

@add_mixin
class B:
    def bar(self) -> int:
        return 2

b = B()
print(b.foo())
print(b.bar())

pyrighttype(cls.__name__, (cls, Mixin), {})行感到困惑,而mypy说不允许从Type[_T1]继承(这是不允许的,但我认为类型检查器无论如何都可能会选择它)


Tags: nameselfaddreturnfoodefbarmixin

热门问题