Python - NamedTuple
在 Python 中,tuple 是不可变的数据结构,可以容纳一组项目。我们已经在前面的章节中讨论了 tuple 的属性和用法。本章中,我们将解释 namedtuple() 及其在 Python 中的用法。
什么是 NamedTuple?
在 Python 中,namedtuple() 是 tuple 的子类,它允许你创建带有命名字段的 tuple。这意味着,你可以使用字段名而不是仅使用数字索引来访问 tuple 的元素。它是 Python 中 collections 模块的一部分。
语法
from collections import namedtuple
# 定义一个 namedtuple
Point = namedtuple('typename', fieldnames )
- 类型名称: typename 是 namedtuple 类的名称。它是一个表示 tuple 类型名称的字符串。
- 字段名称: 字段名称是 tuple 中元素的名称。它们被定义为字符串列表。
在 Python 中创建 NamedTuple
要创建 namedtuple,需要从 collections 模块导入 namedtuple 函数。然后,你可以通过指定其名称和字段名称来定义 namedtuple。
以下示例展示了如何创建名为 Point 的 namedtuple,带有 x 和 y 字段 −
from collections import namedtuple
# 定义一个 namedtuple
Vertex = namedtuple('Vertex', ['x', 'y'])
# 创建实例
v = Vertex(10, 20)
# 访问字段
print("Vertex-1:", v.x)
print("Vertex-2:", v.y)
上述代码的输出将是 −
Vertex-1: 10 Vertex-2: 20
访问 NamedTuple 字段
我们已经看到了如何使用点表示法(即使用键名)访问 namedtuple 的字段。还有一些其他方式也可以访问字段 −
- 通过索引访问 − 你可以使用索引访问字段,就像普通 tuple 一样。
- 通过键名访问 − 你也可以使用键名访问字段,类似于 dictionary。
- 使用 getattr() 访问 − 你可以使用 getattr() 函数通过名称访问字段。
示例:通过索引访问
在本示例中,我们将使用索引访问 namedtuple 的字段。
from collections import namedtuple
# 定义一个 namedtuple
Point = namedtuple('Point', ['x', 'y'])
# 创建实例
p = Point(10, 20)
# 通过索引访问字段
print("Point-1", p[0])
print("Point-2", p[1])
上述代码的输出将是 −
Point-1 10 Point-2 20
示例:通过键名访问
在本示例中,我们将使用键名访问 namedtuple 的字段。
from collections import namedtuple
# 定义一个 namedtuple
Point = namedtuple('Point', ['x', 'y'])
# 创建实例
p = Point(10, 20)
# 通过键名访问字段
print("Point-1:", p.x)
print("Point-2:", p.y)
上述代码的输出将是 −
Point-1: 10 Point-2: 20
示例:使用 getattr() 访问
在本示例中,我们将使用 getattr() 函数访问 namedtuple 的字段。
from collections import namedtuple
# 定义一个 namedtuple
Point = namedtuple('Point', ['x', 'y'])
# 创建实例
p = Point(10, 20)
# 使用 getattr() 访问字段
print("getattr(p, 'x'):", getattr(p, 'x'))
print("getattr(p, 'y'):", getattr(p, 'y'))
上述代码的输出将是 −
getattr(p, 'x'): 10 getattr(p, 'y'): 20
NamedTuple 方法
NamedTuple 带有额外的内置方法来处理常见操作。下面的章节将通过示例讨论其中一些方法。
_fields() 方法
_fields() 方法用于访问 namedtuple 的字段名称。它不需要任何参数,并返回字段名称的 tuple。
以下示例演示了如何使用 _fields() 方法 −
from collections import namedtuple
# 定义一个 namedtuple
Point = namedtuple('Point', ['x', 'y'])
# 创建一个实例
p = Point(10, 20)
# 使用 _fields() 访问字段
print("Fields of p:", p._fields)
上述代码的输出将是 −
Fields of p: ('x', 'y')
_replace() 方法
_replace() 方法用于创建 namedtuple 的新实例,其中一个或多个字段被替换为新值。它接受关键字参数,其中键是字段名称,值是分配的新值。
以下示例演示了如何使用 _replace() 方法 −
from collections import namedtuple
# 定义一个 namedtuple
Point = namedtuple('Point', ['x', 'y'])
# 创建一个实例
p = Point(10, 20)
# 替换字段值
p2 = p._replace(x=30)
# 访问字段
print("p2.x:", p2.x)
print("p2.y:", p2.y)
上述代码的输出将是 −
p2.x: 30 p2.y: 20
_asdict() 方法
_asdict() 方法用于将 namedtuple 转换为普通的 dictionary。此函数返回由 namedtuple 的映射值构建的 OrderedDict()。
以下示例演示了如何使用 _asdict() 方法 −
from collections import namedtuple
# 定义一个 namedtuple
Point = namedtuple('Point', ['x', 'y'])
# 创建一个实例
p = Point(10, 20)
# 转换为 dictionary
d = p._asdict()
print(d)
上述代码的输出将是 −
{'x': 10, 'y': 20}
_make() 方法
_make() 方法用于从一个 iterable(如 list 或 tuple)创建 namedtuple 的新实例。
以下示例演示了如何使用 _make() 方法 −
from collections import namedtuple
# 定义一个 namedtuple
Point = namedtuple('Point', ['x', 'y'])
# 创建一个实例
p = Point(10, 20)
# 使用 _make() 创建新实例
p2 = Point._make([30, 40])
# 访问字段
print("p2.x:", p2.x)
print("p2.y:", p2.y)
上述代码的输出将是 −
p2.x: 30 p2.y: 40
**(双星号)运算符
**(双星号)运算符用于将 namedtuple 的字段解包为关键字参数。这在将 namedtuple 的字段传递给接受关键字参数的 function 时非常有用。
以下示例演示了如何使用 ** 运算符 −
import collections
# 声明 namedtuple()
Student = collections.namedtuple('Student',
['name', 'age', 'DOB'])
# 添加值
S = Student('farhan', '23', '2541997')
# 初始化 iterable
li = ['nishu', '19', '411997']
# 初始化 dict
di = {'name': "ravi", 'age': 24, 'DOB': '1391997'}
# 使用 ** 运算符从 dictionary 返回 namedtuple
print("The namedtuple instance from dict is : ")
print(Student(**di))
上述代码的输出将是 −
The namedtuple instance from dict is : Student(name='ravi', age=24, DOB='1391997')
NamedTuple 与 Dictionary 和 Class 的比较
NamedTuple、Dictionary 和 Class 的主要区别如下 −
| 特性 | NamedTuple | Dictionary | Class |
|---|---|---|---|
| 语法 | 简单,就像 tuple 一样 | 键值对 | 更复杂,带有方法和属性 |
| 访问元素 | 通过名称或索引 | 通过键 | 通过属性 |
| 可变性 | 不可变 | 可变 | 可变 |
| 内存效率 | 最高效 | 效率较低 | 最低效 |
结论
在本章中,我们学习了 Python 中的 namedtuples,以及它与 dictionaries 和 classes 的区别。一个常见问题是,何时使用 NamedTuple、Dictionary 或 Class?当你需要一个具有固定字段的不可变对象时,即如果你想要 tuples 和 dictionaries 的特性,可以使用 NamedTuple。当你需要一个具有动态键的可变对象时,可以使用 Dictionary,而当你需要具有方法和行为的复杂数据结构时,使用 Class。