类装饰器上的 Mypy 注释

Posted

技术标签:

【中文标题】类装饰器上的 Mypy 注释【英文标题】:Mypy annotation on a class decorator 【发布时间】:2019-11-13 06:32:03 【问题描述】:

我在 Python 中使用类装饰器,但无法确定要为我的类提供哪种类型注释以使 mypy 开心。

我的代码如下:

from typing import Type
from pprint import pformat


def betterrepr(cls:Type[object]):
    """Improve representation of a class"""

    class improved_class(cls):  # line 12
        def __repr__(self) -> str:
            return f"Instance of cls.__name__, vars = pformat(vars(self))"

    return improved_class

我目前遇到以下 2 个错误:

myprog.py:12:错误:无效类型“cls”

myprog.py:12: 错误:无效的基类

cls 的类型应该使用什么(顺便说一句,将这个关键字用于作为参数的类是 Pythonic 吗?)?

谢谢

【问题讨论】:

请注意,您可以修改 cls,而不是从它继承。 cls 是类的规范名称,例如作为classmethod 的第一个参数。 “[...] 'cls' 是任何已知为类的变量或参数的首选拼写,尤其是类方法的第一个参数。”来自PEP8 对于只修改类而不创建新类型的典型类装饰器:Mypy 使用插件来实现这种行为。对于类装饰器,您可以使用 dataclass plugin 作为参考。对于 Pyright(Microsoft 的快速类型检查器),您可以使用 dataclass transforms。 【参考方案1】:

使用函数参数作为基类是currently not supported by mypy。您唯一的选择是使用type: ignore 注释或base: Any = cls 之类的虚拟别名来消除错误。

即使没有注释clsmypy 也能正确推断出用betterrepr 装饰的类的类型。要记录您的装饰器返回的类类似于装饰类,请使用TypeVar

from typing import Type, TypeVar
from pprint import pformat

T = TypeVar('T')


def betterrepr(cls: Type[T]) -> Type[T]:
    """Improve representation of a class"""
    class IClass(cls):  # type: ignore
        def __repr__(self) -> str:
            return f"Instance of cls.__name__, vars = pformat(vars(self))"
    return IClass

【讨论】:

以上是关于类装饰器上的 Mypy 注释的主要内容,如果未能解决你的问题,请参考以下文章

typescript DI - Bootstrap和Inject装饰器上的提供者注册

python 装饰器:装饰器实例类装饰器(装饰函数)

python 装饰器:装饰器实例类装饰器(装饰函数)

使用 TypeVar 在 MyPy 中使用参数键入装饰器会产生预期的无人居住类型

为啥我会在装饰器上使用责任链?

使用两种不同的装饰器实现来装饰所有类方法的元类