有问题的是使用的元类typing.NamedTuple
;这个元类ignores所有基类并且只生成一个collections.namedtuple()
添加注释信息的类(复制直接在类上定义的任何其他属性)。
您可以定义自己的元类(它必须是typing.NamedTupleMeta
),这会添加您的附加基类after生成命名元组类:
import typing
NamedTuple = typing.NamedTuple
if hasattr(typing.NamedTuple, '__mro_entries__'):
# Python 3.9 fixed and broke multiple inheritance in a different way
# see https://github.com/python/cpython/issues/88089
NamedTuple = typing._NamedTuple
class MultipleInheritanceNamedTupleMeta(typing.NamedTupleMeta):
def __new__(mcls, typename, bases, ns):
if NamedTuple in bases:
base = super().__new__(mcls, '_base_' + typename, bases, ns)
bases = (base, *(b for b in bases if not isinstance(b, NamedTuple)))
return super(typing.NamedTupleMeta, mcls).__new__(mcls, typename, bases, ns)
class Base1(metaclass=MultipleInheritanceNamedTupleMeta):
def foo(self):
print(self.__annotations__)
class Test1(NamedTuple, Base1):
x: int
y: int
请注意,这不会让您继承字段!那是因为你must生成一个新的namedtuple
任意字段组合的类。上述产生以下结构:
-
Test1
, inherits from
-
_base_Test1
- the actual typing.NamedTuple
generated namedtuple
Base1
这按要求工作:
>>> x = Test1(1, 2)
>>> x.foo()
{'x': <class 'int'>, 'y': <class 'int'>}
从技术上讲,您只需要在 Python 3.10 之前的 Python 版本中使用上述内容。 Python 3.9 进行了重构NamedTuple
修复了这个问题背后的特定元类问题的实现,但随后引入了一个不同的通过明确提出问题TypeError
声明不支持多重继承。这TypeError
was 作为错误提出 https://github.com/python/cpython/issues/88089,因为存在使用多重继承的有效用例NamedTuple
,并且该异常在 Python 3.11 中被删除。
不过,您可以在 Python 3.11 中安全地使用此答案中的代码。