我有一个类装饰器,它向装饰的类添加一些函数和字段。
@mydecorator
@dataclass
class A:
a: str = ""
(通过setattr()
)添加了一个.save()
函数和一组作为单独指令的数据类字段信息。
我希望VScode和mypy能够正确识别它,以便在使用以下命令时:
a=A()
a.save()
或a.my_fields_dict
,正确地识别这2个。
有什么方法可以做到这一点吗?也许可以在运行时修改类A
的类型注解?
我有一个类装饰器,它向装饰的类添加一些函数和字段。
@mydecorator
@dataclass
class A:
a: str = ""
(通过setattr()
)添加了一个.save()
函数和一组作为单独指令的数据类字段信息。
我希望VScode和mypy能够正确识别它,以便在使用以下命令时:
a=A()
a.save()
或a.my_fields_dict
,正确地识别这2个。
有什么方法可以做到这一点吗?也许可以在运行时修改类A
的类型注解?
1条答案
按热度按时间vaqhlq811#
靶区; DR
您尝试做的事情在当前类型系统中是不可能的。
1.交叉点类型
如果通过装饰器添加到类中的属性和方法是静态的(从某种意义上说,它们不仅仅是在运行时已知的),那么通过混合protocol
P
,你所描述的实际上是对任何给定类T
的扩展,该协议定义了方法save
等等。要对此进行注解,需要
T & P
的一个交集,如下所示:你可能会注意到
Intersection
的导入明显缺失了,这是因为尽管它是Python类型系统的most requested features之一,但到目前为止仍然缺失,目前还没有办法在Python类型中表达这个概念。2.类装饰器问题
现在唯一的解决方法是定制一个实现,以及一个相应的插件,用于您选择的类型检查器。我刚刚偶然发现了
typing-protocol-intersection
包,它正好为mypy
做了这件事。如果您安装了它并将
plugins = typing_protocol_intersection.mypy_plugin
添加到您的mypy
配置中,您可以编写如下代码:但是这里我们遇到了下一个问题,通过
mypy
使用reveal_type(A.bar())
测试这个问题将得到以下结果:然而,如果我们这样做:
我们没有收到
mypy
和note: Revealed type is "builtins.str"
的投诉。尽管我们之前所做的是等效的!这不是插件的bug,而是
mypy
内部的bug。这是另一个long-standing issue,mypy
没有正确处理类装饰器。该问题线程中的一个人甚至提到了您的用例以及所需的交集类型。
自己动手
换句话说,你只能等到这两个漏洞被修补好,或者你可以希望至少
mypy
的装饰器问题很快被修复,同时为交集类型编写你自己的VSCode插件,也许你可以和我上面提到的mypy
插件背后的人聚在一起。