在我看来NamedTuple
和TypedDict
非常相似,Python开发人员自己也意识到了这一点。
关于PEP,我宁愿添加有关NamedTuple和TypedDict的公共部分,它们非常相似,后者已经在结构上起作用。你怎么看? source
但是Guido对此不太确定。
我不确定NamedTuple和TypedDict是否真的一样(除了它们都是试图在静态类型的世界中处理过时的模式)。
因此,这是我懒惰的尝试,目的是使其他人在官方文档似乎缺乏的情况下进行清晰的比较。
答案 0 :(得分:4)
Python及其社区正在努力解决“结构”问题:如何最好地将相关值分组到复合数据对象中,从而可以逻辑/轻松地访问组件(通常按名称)。有许多竞争方法:
collections.namedtuple
实例tuple
和list
之类的序列,每个位置/位置都有隐含含义(古朴但极为普遍)对于“应该有一种,最好只有一种明显的方式来做到这一点”。
typing
库和Mypy(就像整个Python社区一样)都在努力解决如何更有效地定义类型/模式(包括复合对象)的问题。您链接到的讨论是该工作的一部分,并试图找到前进的方向。
NamedTuple
是collections.namedtuple
工厂产生的结构化对象的输入超类; TypedDict
Mypy尝试定义使用固定模式字典时出现的键和相应的值类型。如果您只是在考虑“我有一组固定的键应该映射到一组固定的类型值”,它们是相似的。但是最终的实现方式和约束条件却大不相同。袋子和盒子相似吗?也许。也许不吧。取决于您的观点和使用方式。倒酒,让讨论开始!
NamedTuple
现在是Python的正式组成部分。
from typing import NamedTuple
class Employee(NamedTuple):
name: str
id: int
TypedDict
不是Python专有的 部分,而是Mypy的一项实验性功能,可将打字打乱到异类的,面向结构的字典使用中。
from mypy_extensions import TypedDict
Movie = TypedDict('Movie', {'name': str, 'year': int})
尽管NamedTuple
和TypedDict
有所不同,但它们都锁定了要使用的特定键以及与每个键对应的值的类型。因此,他们的目标基本上是相同的目标:对复合/结构类型使用有用的键入机制。
Python的标准typing.Dict
专注于更均匀的并行映射,定义键/值类型,而不是键本身。因此,在定义碰巧存储在字典中的复合对象时,它并不是很有用。
ConnectionOptions = Dict[str, str]
答案 1 :(得分:3)
一个TypedDict
(在3.8+中)是
简单类型的名称空间。在运行时,它等同于简单的字典。
而NamedTuple
是“元组子类”。请注意
命名元组实例没有按实例的字典,因此它们是轻量级的,并且不需要比常规元组更多的内存。
和(from here)
NamedTuple子类也可以具有文档字符串和方法
用我自己的话来说,NamedTuple
更像是自定义对象,而TypedDict
更像是类型化的字典。
我还没有检查,但是从这些描述中,我希望NamedTuples
比TypedDict
拥有一些(较小的)运行时和内存优势。
但是,例如,如果您使用的API期望dict
,则最好使用TypedDict
,因为它是dict
(尽管您也可以创建{ dict
中的{1}}通过其NamedTuple
方法)。
答案 2 :(得分:1)
有一些细微的差异。请注意,这些容器还没有永远存在过:
如果可能并且我希望冻结值,我会选择NamedTuple
。否则,我将使用数据类。
from dataclasses import dataclass
from typing import NamedTuple, TypedDict
from enum import Enum
class Gender(Enum):
MALE = "male"
FEMALE = "female"
## Class definition: Almost the same
@dataclass
class UserDataC:
name: str
gender: Gender
class UserTuple(NamedTuple):
name: str
gender: Gender
class UserNDict(TypedDict):
name: str
gender: Gender
## Object Creation: Looks the same
anna_datac = UserDataC(name="Anna", gender=Gender.FEMALE)
anna_tuple = UserTuple(name="Anna", gender=Gender.FEMALE)
anna_ndict = UserNDict(name="Anna", gender=Gender.FEMALE)
## Mutable values vs frozen values
anna_datac.gender = Gender.MALE
# anna_tuple.gender = Gender.MALE # AttributeError: can't set attribute
anna_ndict["gender"] = Gender.MALE
# AttributeError: 'dict' object has no attribute 'gender'
# anna_ndict.gender = Gender.MALE
## New attribute
# Note that you can add new attributes like this.
# Python will not complain. But mypy will.
anna_datac.password = "secret" # Dataclasses are extensible
# anna_tuple.password = "secret" # AttributeError - named tuples not
# anna_ndict.password = "secret" # AttributeError - TypedDict not
anna_ndict["password"] = "secret"
## isinstance
assert isinstance(anna_tuple, tuple)
assert isinstance(anna_ndict, dict)
答案 3 :(得分:0)
NamedTuple
是一种特定类型。顾名思义,这是一个扩展为具有命名条目的元组。
TypedDict
不是真实的对象,您不能(或至少不应)使用它,而是用于添加类型信息(用于mypy类型检查器)以在词典中的场景中注释类型具有各种不同类型的键,即基本上所有应该使用NamedTuple
的地方。注释您不想重构的现有代码非常有用。