namedtuple和NamedTuple有什么区别?

Wos*_*oss 41 python python-3.x

typing模块的文件说,下面的两段代码是等效的.

from typing import NamedTuple

class Employee(NamedTuple):
    name: str
    id: int
Run Code Online (Sandbox Code Playgroud)

from collections import namedtuple

Employee = namedtuple('Employee', ['name', 'id'])
Run Code Online (Sandbox Code Playgroud)

它们是完全相同的,如果不是,两个实现之间有什么区别?

wim*_*wim 36

由子类生成的类型typing.NamedTuple等同于一个collections.namedtuple,而是用__annotations__,_field_types_field_defaults属性添加.出于所有实际目的,生成的代码将表现相同,因为Python中的任何内容当前都不会对那些键入相关属性起作用(但您的IDE可能会使用它们).作为开发人员,使用typingnamedtuples 的模块允许更自然的声明性接口:

  • 您可以轻松指定字段的默认值
  • 您不需要重复两次类型名称("员工")
  • 您可以直接自定义类型(例如,添加文档字符串或某些方法)

和以前一样,你的类将是一个子类collections.namedtuple,而实例将defaults像往常一样.有趣的是,您的类不会是以下的子类tuple:

>>> class Employee(NamedTuple):
...     name: str
...     id: int
...     
>>> issubclass(Employee, NamedTuple)
False
>>> isinstance(Employee(name='guido', id=1), NamedTuple)
False
Run Code Online (Sandbox Code Playgroud)

如果您想知道原因,请继续阅读以获取有关当前实现细节的更多信息.tuple是一个类,它使用元类和自定义NamedTuple来处理注释,然后它委托typing.NamedTuple,无论如何,构建和返回类型.您可能已经从小写的名称约定中猜到,__new__不是类型/类 - 它是工厂函数.它的工作原理是构建一串Python源代码,然后调用collections.namedtuple此字符串.将生成的构造函数抠出一个命名空间包含在元类的3个参数的调用collections.namedtuple来构建并返回类.这解释了上面看到的奇怪的继承断裂,exec使用元类来使用不同的元类来实例化类.

  • @dfundako 通过对生成的类型进行子类化,可以使用`collections.namedtuple`。但是 `typing.NamedTuple` 允许更简单的界面。 (2认同)