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相关问答推荐

"安装serial vs安装psyserial header,"""

PythonPandas -通过知道位置(Loc)而不是索引来删除行

无法使用诗词安装PyYaml

regexp多重前瞻行为的解释

如何将列表和字典逐行组合在一起

有没有办法使用 python opencv 计算与图像的白色距离

Pygame 错误地渲染等距图像

从 h264 帧解析数据包时 PyAV 不一致

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

python3:字节与字节数组,并转换为字符串和从字符串转换

使用 python 正则表达式匹配日期

为 python3 安装 opencv

'~'(波浪号)运算符在 Python 中的应用

str.format_map(mapping) 和 str.format 有什么区别

__new__ 方法给出错误 object.__new__() 只接受一个参数(要实例化的类型)

django - 值更改后自动更新日期

使用打印时,用+连接是否比用,分隔更有效?

在 ubuntu 20.04 中安装 libpq-dev 时出现问题

在 linux mint 上安装 python3-venv 模块

在 PyCharm 中配置解释器:请使用不同的 SDK 名称