因此,这是一个元类冲突,因为在python
3.6中键入
NamedTuple和
Generic使用不同的元类(
typing.NamedTuplemeta和
typing.Genericmeta),而这是python无法处理的。恐怕除了从
tuple值中继承和手动初始化值外,没有其他解决方案:
T1 = TypeVar("T1")T2 = TypeVar("T2")class Group(tuple, Generic[T1, T2]): key: T1 group: List[T2] def __new__(cls, key: T1, group: List[T2]): self = tuple.__new__(cls, (key, group)) self.key = key self.group = group return self def __repr__(self) -> str: return f'Group(key={self.key}, group={self.group})'Group(1, [""]) # --> Group(key=1, group=[""])由于PEP
560和563,此问题已在python
3.7中修复:
Python 3.7.0b2 (v3.7.0b2:b0ef5c979b, Feb 28 2018, 02:24:20) [MSC v.1912 64 bit (AMD64)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> from __future__ import annotations>>> from typing import *>>> T1 = TypeVar("T1")>>> T2 = TypeVar("T2")>>> class Group(NamedTuple, Generic[T1, T2]):... key: T1... group: List[T2]...>>> g: Group[int, str] = Group(1, [""])>>> gGroup(key=1, group=[''])当然,在python 3.7中,您只能使用轻量级(且易变)但用途相似的数据类。
from dataclasses import dataclass, astuplefrom typing import Generic, TypeVar, ListT1 = TypeVar('T1')T2 = TypeVar('T2')@dataclassclass Group(Generic[T1, T2]): key: T1 group: List[T2] # if you want to be able to unpack like a tuple... def __iter__(self): yield from astuple(self)g: Group[int, str] = Group(1, ['hello', 'world'])k, v = gprint(g)尽管我没有检查过,类型检查器在python 3.7中如何处理我的解决方案/您的解决方案。我怀疑这可能不是无缝的。
编辑
我找到了另一个解决方案-制作一个新的元类
import typingfrom typing import *class NamedTupleGenericmeta(typing.NamedTuplemeta, typing.Genericmeta): passclass Group(NamedTuple, Generic[T1,T2], metaclass=NamedTupleGenericmeta): key: T1 group: List[T2]Group(1, ['']) # --> Group(key=1, group=[''])



