首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >命名元组和NamedTuple有什么区别?

命名元组和NamedTuple有什么区别?
EN

Stack Overflow用户
提问于 2018-06-09 02:25:21
回答 1查看 7.2K关注 0票数 73

typing module documentation说下面的两个代码片段是等价的。

from typing import NamedTuple

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

from collections import namedtuple

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

它们是完全相同的东西吗?或者,如果不是,两个实现之间的区别是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-09 03:22:46

通过子类化typing.NamedTuple生成的类型等同于collections.namedtuple,但添加了__annotations___field_types_field_defaults属性。出于所有实际目的,生成的代码的行为都是一样的,因为Python中目前没有任何东西作用于那些与类型相关的属性(尽管您的IDE可能会使用它们)。

作为开发人员,对命名元组使用typing模块可以提供更自然的声明性接口:

  • 您可以轻松地为字段指定默认值(在Python3.7中,编辑__:在Python3.7中,collections.namedtuple 使其不再是advantage)
  • You无需重复两次类型名称("Employee")
  • You可以直接自定义类型(例如,添加文档字符串或某些方法)

与以前一样,您的类将成为tuple的子类,实例将照常成为tuple的实例。有趣的是,您的类不是NamedTuple的子类。如果您想知道原因,请继续阅读有关实现细节的更多信息。

from typing import NamedTuple

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

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。这解释了上面看到的奇怪的继承中断,NamedTuple使用元类来使用不同的元类来实例化类对象。

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

票数 72
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50766461

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档