命名元组的构造方式使得继承typing.NamedTuple
类目前还不可能。您必须编写自己的元类来扩展typing.NamedTupleMeta
class 使子类化工作,即使如此生成的类collections.namedtuple()只是不是为了扩展而构建的 https://stackoverflow.com/questions/28500524/python-extending-a-predefined-named-tuple/28500620#28500620.
相反,您想使用新的dataclasses module https://docs.python.org/3.7/library/dataclasses.html定义您的类并实现继承:
from dataclasses import dataclass
@dataclass(frozen=True)
class Base:
x: int
y: int
@dataclass(frozen=True)
class BaseExtended(Base):
z: str
该模块是 Python 3.7 中的新模块,但您可以pip install dataclasses向后移植 https://pypi.org/project/dataclasses/#description在 Python 3.6 上。
上面定义了两个不可变类x
and y
属性,与BaseExtended
类又添加了一个属性。BaseExtended
是一个完整的子类Base
,因此出于打字目的,符合以下要求DoSomething()
功能。
这些类不是完整命名的元组,因为它们没有长度或支持索引,但这是通过创建继承自的基类来轻松添加的collections.abc.Sequence
,添加两个通过索引访问字段的方法。如果你添加order=True
to the @dataclass()
装饰器然后你的实例变得完全可排序,就像(命名)元组一样:
from collections.abc import Sequence
from dataclasses import dataclass, fields
class DataclassSequence(Sequence):
# make a dataclass tuple-like by accessing fields by index
def __getitem__(self, i):
return getattr(self, fields(self)[i].name)
def __len__(self):
return len(fields(self))
@dataclass(frozen=True, order=True)
class Base(DataclassSequence):
x: int
y: int
MyPy 很快就会支持dataclasses明确地 https://github.com/python/mypy/issues/4792;在 0.600 版本中,您仍然会收到错误,因为它无法识别dataclasses
模块导入或__new__
方法已生成。
在 Python 3.6 及更早版本中,您还可以安装attrs project http://www.attrs.org/en/stable/达到同样的效果;上面的序列基类看起来像这样使用attrs
:
from collections.abc import Sequence
import attr
class AttrsSequence(Sequence):
# make a dataclass tuple-like by accessing fields by index
def __getitem__(self, i):
return getattr(self, attr.fields(type(self))[i].name)
def __len__(self):
return len(attr.fields(type(self)))
@attr.s(frozen=True, auto_attribs=True)
class Base(AttrsSequence):
x: int
y: int
dataclasses
是直接基于attrs
, with attrs
提供更多功能; mypy 完全支持使用以下命令生成的类attrs
.