[英]Python typing support for NamedTuple
请检查以下代码
import typing
import abc
class A(abc.ABC):
@abc.abstractmethod
def f(self) -> typing.NamedTuple[typing.Union[int, str], ...]:
...
class NT(typing.NamedTuple):
a: int
b: str
class B(A):
def f(self) -> NT:
return NT(1, "s")
print(B().f())
我收到一个错误。 在父类A
我想定义方法f
以便我指示任何子类都应该通过返回一个NamedTuple
由int
ot str
字段组成的NamedTuple
来覆盖它。
但我得到一个错误说:
TypeError: 'NamedTupleMeta' object is not subscriptable
更改签名如下有帮助,但是我将如何告诉打字系统子类可以返回只有 int 和 str 的 NamedTuples
class A(abc.ABC):
@abc.abstractmethod
def f(self) -> typing.NamedTuple:
...
问题是从根本上来说typing.NamedTuple
不是一个正确的类型。 它本质上允许您使用继承和类型注释的语法来使用类工厂collections.namedtuple
。 是糖。
这是误导。 通常,当我们期望:
class Foo(Bar):
pass
foo = Foo()
print(isinstance(foo, Bar))
总是打印True
。 但实际上,通过元类机制, typing.NamedTuple
只是使某些东西成为tuple
的后代,就像collections.namedtuple
一样。 事实上,实际上它存在的唯一原因是使用NamedTupleMetaclass
来拦截类的创建。 也许以下内容会有所启发:
>>> from typing import NamedTuple
>>> class Employee(NamedTuple):
... """Represents an employee."""
... name: str
... id: int = 3
...
>>> isinstance(Employee(1,2), NamedTuple)
False
>>>
>>> isinstance(Employee(1,2), tuple)
True
有些人可能会觉得这很肮脏,但正如 Python 之禅中所述,实用性胜过纯粹性。
请注意,人们经常对collections.namedtuple
感到困惑,它本身不是一个类,而是一个类工厂。 所以:
>>> import collections
>>> Point = collections.namedtuple("Point", "x y")
>>> p = Point(0, 0)
>>> isinstance(p, collections.namedtuple)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: isinstance() arg 2 must be a type or tuple of types
但是注意,通过生成的类namedtuple
/ NamedTuple
做动作,当你从他们那里继承了预期。
请注意,您的解决方案:
import typing
import abc
class A(abc.ABC):
@abc.abstractmethod
def f(self) -> typing.Tuple:
...
class NT(typing.NamedTuple):
a: int
b: str
class B(A):
def f(self) -> NT:
return NT(1, "s")
print(B().f())
不通过 mypy:
(py38) juan$ mypy test_typing.py
test_typing.py:18: error: Return type "NT" of "f" incompatible with return type "NamedTuple" in supertype "A"
Found 1 error in 1 file (checked 1 source file)
但是,usint Tuple
可以:
class A(abc.ABC):
@abc.abstractmethod
def f(self) -> typing.Tuple[typing.Union[str, int],...]:
...
虽然,这可能不是很有用。
你真正想要的是某种结构类型,但我想不出任何方法来使用typing.Protocol
。 基本上,它不能表达“任何具有可变数量属性的类型,所有这些属性都在typing.Union[int, str]
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.