小编典典

Python中的“命名元组”是什么?

all

阅读Python 3.1 中的变化,我发现了一些……意想不到的东西:

sys.version_info 元组现在是一个 命名元组

我以前从未听说过命名元组,我认为元素可以通过数字(如在元组和列表中)或键(如在 dicts 中)来索引。我从没想过它们会被双向索引。

因此,我的问题是:

  • 什么是命名元组?
  • 如何使用它们?
  • 为什么/何时应该使用命名元组而不是普通元组?
  • 为什么/何时应该使用普通元组而不是命名元组?
  • 是否有任何类型的“命名列表”(命名元组的可变版本)?

阅读 110

收藏
2022-02-28

共1个答案

小编典典

命名元组基本上是易于创建的轻量级对象类型。命名元组实例可以使用类似对象的变量解引用或标准元组语法来引用。它们可以与struct其他常见记录类型类似地使用,但它们是不可变的。它们是在
Python 2.6 和 Python 3.0 中添加的,尽管在 Python 2.4
中有一个实现方法

例如,将一个点表示为一个元组是很常见的(x, y)。这导致如下代码:

pt1 = (1.0, 5.0)
pt2 = (2.5, 1.5)

from math import sqrt
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)

使用命名元组它变得更具可读性:

from collections import namedtuple
Point = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)

from math import sqrt
line_length = sqrt((pt1.x-pt2.x)**2 + (pt1.y-pt2.y)**2)

但是,命名元组仍然向后兼容普通元组,因此以下内容仍然有效:

Point = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)

from math import sqrt
# use index referencing
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
 # use tuple unpacking
x1, y1 = pt1

因此, 您应该使用命名元组而不是元组,只要您认为对象表示法会使您的代码更 Python 和更易于阅读
。我个人已经开始使用它们来表示非常简单的值类型,尤其是在将它们作为参数传递给函数时。它使函数更具可读性,而无需查看元组打包的上下​​文。

此外, 您还可以用它们替换 没有函数 __、只有字段的普通 不可变类。 您甚至可以使用命名元组类型作为基类:

class Point(namedtuple('Point', 'x y')):
    [...]

但是,与元组一样,命名元组中的属性是不可变的:

>>> Point = namedtuple('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
AttributeError: can't set attribute

如果您希望能够更改值,则需要另一种类型。可变记录类型有一个方便的配方,它允许您为属性设置新值。

>>> from rcdtype import *
>>> Point = recordtype('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
>>> print(pt1[0])
    2.0

但是,我不知道任何形式的“命名列表”可以让您添加新字段。在这种情况下,您可能只想使用字典。命名元组可以转换为使用pt1._asdict()which
返回的字典,{'x': 1.0, 'y': 5.0}并且可以使用所有常用的字典函数对其进行操作。

如前所述,您应该查看文档以获取构建这些示例的更多信息。

2022-02-28