我有一个函数,该函数接受一个派生自类NamedTuple
并将其转换为模式的类。但是,当我在以下代码上运行MyPy时,它将失败Argument 1 to "to_schema" has incompatible type "Type[Foo]"; expected "Type[NamedTuple]"
from typing import NamedTuple, Type
def to_schema(named_tuple: Type[NamedTuple]):
pass
class Foo(NamedTuple):
pass
to_schema(Foo)
有没有办法正确键入代码,以便通过MyPy进行类型检查?
编辑:Python文档声明Type[Foo]
接受Foo
(https://docs.python.org/3/library/typing.html#typing.Type)的任何子类。NamedTuple
对于我们的数据模型中的实体,我有多个的子类,因此我正在寻找一种以类型检查的方式注释函数的方法。
您的代码的根本问题在于这NamedTuple
不是实际的类型-实际上,它只是一种特殊的“类型构造函数”,它综合了全新的类和类型。例如,如果您尝试打印的值Foo.__mro__
,则会看到(<class '__main__.Foo'>, <class 'tuple'>, <class 'object'>)
-NamedTuple
根本不存在。
这意味着NamedTuple
实际上根本就不是一个有效的类型,就这一点而言,mypy只是让您默默地Type[NamedTuple]
开始构建,这让我感到有些惊讶。
要变通解决此问题,您有几种可能的方法:
而不要使用Type[NamedTuple]
,请使用Type[tuple]
或Type[Tuple[Any]]
。
你Foo
真的是一个元组的一个亚型,毕竟。
如果需要仅在namedtuple中存在的方法或字段,请使用自定义协议。例如,如果您特别需要_asdict
namedtuples中的方法,则可以执行以下操作:
from typing_extensions import Protocol
class NamedTupleProto(Protocol):
def _asdict(self) -> Dict[str, Any]: ...
def to_schema(x: Type[NamedTupleProto]) -> None: pass
class Foo(NamedTuple):
pass
to_schema(Foo)
请注意typing_extensions
,尽管有计划将协议正式化并在某个时候将其添加到Python中,您仍需要安装第三方库才能使用它。(我忘记了计划是Python 3.7还是3.8)。
在调用上添加类型忽略或to_schema
强制转换以使mypy静音。这不是最大的解决方案,但也是最快的解决方案。
有关相关讨论,请参见此问题。基本上,在mypy团队中已经达成共识,有人应该对此NamedTuple做些事情,无论是通过添加错误消息还是通过添加官方认可的协议,但我认为人们太忙于其他任务/错误,无法推动这一发展。 。(因此,如果您无聊并且正在寻找可以做的事情...)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句