tuples - python “named tuples” 是什么?

  显示原文与译文双语对照的内容

读取中更改 python 3.1,我发现了一些东西- - 意外:

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

我以前从未听说过命名元组,我认为元素可以用数字( 在元组和列表中) 或者键( 在dicts中) 来索引。 我从不期望它们可以同时被索引。

因此,我的问题是:

  • 什么是命名元组?
  • 如何使用它们?
  • 为什么应该使用命名元组而不是正常元组?
  • 为什么应该使用正规元组而非命名元组?
  • 是否有任何类型的"命名列表"( 命名元组的可变版本)?
时间:

命名元组基本上很容易创建,轻量级对象类型。 可以使用变量deferencing或者标准元组语法引用命名元组实例。 它们可以类似于 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

因此,物体你应该使用命名元组元组而不是你认为的任何位置表示法来使代码更 Pythonic 和更易于认读 。 我亲自开始使用它们来表示非常简单的值类型,特别是将它们作为参数传递给函数时。 它使得函数更具可读性,而无需查看元组打包的上下文。

them,此外,也可以代替普通不可变类,没有函数,只有 fields. 你甚至可以将命名元组类型用作基类:


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

如果你想要更改值,你需要另一个类型。 对于可变 recordtypes,有一个方便的配方,它允许你为属性设置新值。


>>> 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() 返回的命名元组可以转换为 {'x': 1.0, 'y': 5.0} 可以用所有常用字典函数操作。

在将这些示例是constructed,已经提到,你应该的检查文档以获取更多资料。

于做一个相关元组 class, namedtuple. 是一种工厂函数 使用该类,我们可以创建可以按名称调用的元组。


import collections

#Create a namedtuple class with names"a""b""c"
Row = collections.namedtuple("Row", ["a","b","c"], verbose=False, rename=False) 

row = Row(a=1,b=2,c=3) #Make a namedtuple from the Row class we created

print row #Prints: Row(a=1, b=2, c=3)
print row.a #Prints: 1
print row[0] #Prints: 1

row = Row._make([2, 3, 4]) #Make a namedtuple from a list of values

print row #Prints: Row(a=2, b=3, c=4)

namedtuples是一个很棒的特性,它们是数据的完美容器。 当你需要"存储"数据时,你将使用元组或者字典,比如:


user = dict(name="John", age=20)

或者:


user = ("John", 20)

字典方法是压倒性的,因为dict是可变的,比元组慢。 另一方面,元组是不可变的和轻量的,但在数据字段的大量条目中缺乏可读性。

namedtuples是这两种方法的完美折衷,具有很好的可读性,lightweightness和不变性( 而且它们是多态的) 。

命名元组允许向代码向后兼容,该代码检查这里版本


>>> sys.version_info[0:2]
(3, 1)

使用这里语法允许将来的代码更加明确


>>> sys.version_info.major
3
>>> sys.version_info.minor
1

...