typing module documentation表示下面的两段代码是等效的.

from typing import NamedTuple

class Employee(NamedTuple):
    name: str
    id: int

from collections import namedtuple

Employee = namedtuple('Employee', ['name', 'id'])

它们是完全一样的吗?如果不是,这两种实现之间的区别是什么?

推荐答案

子类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 namespaceincluded in a 3-argument invocation of the metaclass type用于构建并返回您的类.这就解释了上述奇怪的继承 destruct ,NamedTuple使用一个元类来实例化类对象.

Behaviour in Python >= 3.9

typing.NamedTupleclass变为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.

Python-3.x相关问答推荐

如何匹配字母,数字,短划线,逗号,但不是如果没有数字和字母?

如何将CSV或FDF数据解析到Python词典并注入到模板PDF表单中?

如何验证具有内部json字符串的json字符串?

如何定义既允许固定单词又允许模式的pydanti.BaseModel?

PYSMB中的进度条

数据类对象列表的字典获取方法-在数据类列表中查找具有特定变量值的数据类

使用 Fetch 提交表单到 Django 视图

在python内的powershell中转义$_

torch.stack([t1, t1, t1], dim=1)与torch.hstack([t1, t1, t1])之间有什么区别?

你能骗PIP 让它相信包已经安装了吗

GEKKO 在没有不等式的模型中抛出不等式定义错误

使用gekko python的混合整数非线性规划

为什么 Multiprocessing 的 Lock 不会阻止其他进程使用对象?

将名字转换成姓氏、首字母和中间字母的格式

无法在 macOS 上的 Anaconda3 python3.6 上安装 OpenCV3

Python:如何在三个列表中找到共同值

如何将numpy数组图像转换为字节?

如何在python中创建代码对象?

Python 3.4 多处理队列比 Pipe 快,出乎意料

为什么异步库比这个 I/O 绑定操作的线程慢?