数据类与typing.NamedTuple主要用例

长话短说

PEP-557在Python标准库中引入了数据类,基本上可以充当与集合.namedtuple类型.namedtuple相同的角色。现在我想知道如何区分namedtuple仍然是更好解决方案的用例

数据类相对于NamedTuple的优势

当然,如果我们需要:

  • 可变对象
  • 继承支持
  • 属性装饰器,可管理属性
  • 即时生成的方法定义或可自定义的方法定义

数据类的优势在同一个PEP中简要说明:为什么不使用namedtuple呢

问:在哪种情况下,namedtuple仍然是更好的选择

但是对于namedtuples,一个相反的问题是:为什么不使用dataclass呢?
我想从性能的角度来看,namedtuple可能更好,但还没有得到证实

范例

我们考虑以下情况:

我们将把页面维度存储在一个小容器中,其中包含静态定义的字段、类型提示和命名访问。不需要进一步的散列、比较等

命名双方法:

输入import NamedTuple的


PageDimensions=NamedTuple(“PageDimensions”,[('width',int),('height',int)])

数据类方法:

从数据类导入数据类
@数据类
类页面尺寸:
宽度:int
高度:整数

哪种解决方案更可取?为什么

另外,这个问题在任何方面都不是这个问题的重复,因为我在这里问的是命名双倍更好的案例,而不是差异(我在问之前检查了文档和来源)

这取决于你的需要。他们每个人都有自己的好处

下面是关于PyCon 2018 Raymond Hettinger上数据类的一个很好的解释-数据类:结束所有代码生成器的代码生成器

Dataclass中,所有实现都是用Python编写的,而在NamedTuple中,所有这些行为都是免费的,因为NamedTuple继承自tuple。而且由于元组结构是用C编写的,因此标准方法在命名元组(散列、比较等)中速度更快

还请注意,数据类基于dict,而命名元组基于元组。因此,使用这些结构有其优点和缺点。例如,使用NamedTuple,空间使用更少,但使用Dataclass,时间访问更快

请看我的实验:

[33]on

:a=PageDimensionsDC(宽度=10,高度=10)
At[34]on:sys.getsizeof(a)+sys.getsizeof(vars(a))
168[34]:Out
At[35]on:%timeit a.width
每个回路43.2纳秒±1.05纳秒(7次运行的平均值±标准偏差,每个10000000个回路)
At[36]on:a=PageDimensionsNT(宽度=10,高度=10)
In[37]:sys.getsizeof(a)
Out[37]:64
At[38]:%timeit a.width中
每个回路63.6纳秒±1.33纳秒(7次运行的平均值±标准偏差,每个10000000个回路)

但是随着NamedTuple属性数量的增加,访问时间保持不变,因为它会为每个属性创建一个具有属性名称的属性。例如,在我们的示例中,新类的命名空间部分如下所示:

来自操作员导入itemgetter的


类名称空间={
...
“宽度”:属性(itemgetter(0,doc=”字段号0的别名),
“高度”:属性(itemgetter(0,doc=”字段号1的别名)**
}

在哪些情况下,命名为tuple仍然是更好的选择

当您的数据结构需要/可以是不可变的、可散列的、可扩展的、可解包的、可比较的时,您可以使用NamedTuple。如果您需要更复杂的东西,例如,数据结构继承的可能性,那么使用Dataclass

发表评论