namedtuple 和 NamedTuple 有什么区别? [英] What's the difference between namedtuple and NamedTuple?

查看:75
本文介绍了namedtuple 和 NamedTuple 有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

typing 模块文档 表示下面的两个代码片段是等效的.

from typing import NamedTuple类员工(NamedTuple):名称:str编号:int

from collections import namedtupleEmployee = namedtuple('Employee', ['name', 'id'])

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

解决方案

通过子类化 typing.NamedTuple 生成的类型等价于 collections.namedtuple,但带有 <添加了 code>__annotations__、_field_types_field_defaults 属性.出于所有实际目的,生成的代码将具有相同的行为,因为 Python 中目前没有任何内容作用于那些与键入相关的属性(不过,您的 IDE 可能会使用它们).

作为开发人员,为命名元组使用 typing 模块可以实现更自然的声明式接口:

  • 您可以轻松地为字段指定默认值(edit:在 Python 3.7 中,collections.namedtuple 有一个新的defaults 关键字 所以这不再是一个优势)
  • 您不需要重复两次类型名称(Employee")
  • 您可以直接自定义类型(例如添加文档字符串或某些方法)

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

<预><代码>>>>类员工(NamedTuple):...名称:str... ID:整数...>>>issubclass(员工,NamedTuple)错误的>>>isinstance(Employee(name='guido', id=1), NamedTuple)错误的

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

The typing module documentation says that the two code snippets below are equivalent.

from typing import NamedTuple

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

and

from collections import namedtuple

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

Are they the exact same thing or, if not, what are the differences between the two implementations?

解决方案

The type generated by subclassing typing.NamedTuple is equivalent to a collections.namedtuple, but with __annotations__, _field_types and _field_defaults attributes added. The generated code will behave the same, for all practical purposes, since nothing in Python currently acts on those typing related attributes (your IDE might use them, though).

As a developer, using the typing module for your namedtuples allows a more natural declarative interface:

  • You can easily specify default values for the fields (edit: in Python 3.7, collections.namedtuple got a new defaults keyword so this is no longer an advantage)
  • You don't need to repeat the type name twice ("Employee")
  • You can customize the type directly (e.g. adding a docstring or some methods)

As before, your class will be a subclass of tuple, and instances will be instances of tuple as usual. Interestingly, your class will not be a subclass of NamedTuple:

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

If you want to know why, read on for more info about the current implementation detail. typing.NamedTuple is a class, it uses metaclasses and a custom __new__ to handle the annotations, and then it delegates to collections.namedtuple, anyway, to build and return the type. As you may have guessed from the lowercased name convention, collections.namedtuple is not a type/class - it's a factory function. It works by building up a string of Python source code, and then calling exec on this string. The generated constructor is plucked out of a namespace and included in a 3-argument invocation of the metaclass type to build and return your class. This explains the weird inheritance breakage seen above, NamedTuple uses a metaclass in order to use a different metaclass to instantiate the class object.

这篇关于namedtuple 和 NamedTuple 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆