namedtuple和NamedTuple之间的区别是什么?

时间:2018-06-08 18:25:21

标签: python python-3.x

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

from typing import NamedTuple

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

from collections import namedtuple

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

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

1 个答案:

答案 0 :(得分:31)

子类化typing.NamedTuple生成的类型等同于collections.namedtuple,但添加了__annotations___field_types_field_defaults属性。出于所有实际目的,生成的代码将表现相同,因为Python中的任何内容当前都不会对那些键入相关属性起作用(但您的IDE可能会使用它们)。

作为开发人员,使用typing模块为您的namedtuples提供了一个更自然的声明性接口:

  • 您可以轻松指定字段的默认值( 编辑 :在Python 3.7中,collections.namedtuple got a new defaults keyword所以这不是更长的优势
  • 您不需要重复两次类型名称("员工")
  • 您可以直接自定义类型(例如,添加文档字符串或某些方法)

和以前一样,您的类将是tuple的子类,并且实例将像往常一样成为tuple的实例。有趣的是,您的类不会是NamedTuple的子类:

>>> class Employee(NamedTuple):
...     name: str
...     id: int
...     
>>> 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构建并返回您的课程。这解释了上面看到的奇怪的继承断裂,NamedTuple使用元类来使用不同的元类来实例化类对象。