子类typing.NamedTuple
生成的类型相当于collections.namedtuple
,但添加了__annotations__
、_field_types
和_field_defaults
个属性.出于所有实际目的,生成的代码的行为都是相同的,因为Python中目前没有任何东西作用于那些与类型相关的属性(不过,您的IDE可能会使用它们).
作为开发人员,将typing
模块用于namedtuples可以提供更自然的声明性界面:
- 您可以轻松地为字段指定默认值(102: in Python 3.7, 101 100 so this is no longer an advantage)
- 您不需要重复两次类型名称("Employee")
- 您可以直接自定义类型(例如添加docstring或某些方法)
和以前一样,您的类将是tuple
的子类,而实例将像往常一样是tuple
的实例.有趣的是,您的类将不是NamedTuple
的子类.如果您想知道原因,请继续阅读以了解有关实施细节的更多信息.
from typing import NamedTuple
class Employee(NamedTuple):
name: str
id: int
Behaviour in Python <= 3.8
>>> issubclass(Employee, NamedTuple)
False
>>> isinstance(Employee(name='guido', id=1), NamedTuple)
False
typing.NamedTuple
是一个类,它使用metaclasses和自定义__new__
来处理注释,然后使用delegates to collections.namedtuple
, anyway, to build and return the type.正如您可能已经从小写名称约定中猜到的,collections.namedtuple
不是一个类型/类——它是一个工厂函数.它的工作原理是构建一个Python源代码字符串,然后在此字符串上调用exec
.generated constructor is plucked out of a namespace和included in a 3-argument invocation of the metaclass type
用于构建并返回您的类.这就解释了上述奇怪的继承 destruct ,NamedTuple
使用一个元类来实例化类对象.
Behaviour in Python >= 3.9
typing.NamedTuple
从class
变为def
.
>>> issubclass(Employee, NamedTuple)
TypeError: issubclass() arg 2 must be a class or tuple of classes
>>> isinstance(Employee(name="guido", id=1), NamedTuple)
TypeError: isinstance() arg 2 must be a type or tuple of types
使用NamedTuple
的多重继承现在是不允许的(它最初没有正常工作).
有关更改,请参见bpo40185/GH-19371.