Python数据结构:利用命名元组解耦序列访问

纸上星河
纸上星河
发布时间:2026-10-13| 2人浏览过
原创

本文介绍Python中如何使用命名元组(namedtuple)将名称映射到序列元素,从而减少对位置索引的依赖。通过对比普通元组,展示namedtuple在提高代码可读性方面的优势,并详解其不可变性、_replace方法的使用及处理可选字段的技巧。

本文介绍一种在Python中将名称映射到序列元素的方法,供读者参考学习。

核心问题在于:如何通过名称直接访问元素,从而降低代码对序列中具体位置索引的依赖。

解决方案是采用命名元组collections.namedtuple()。这是一个工厂函数,用于生成标准元组类型的子类。用户需提供类型名称及字段名称,该函数将返回一个可实例化的类,允许通过预定义的字段名传入值并进行访问。

命名元组的核心价值在于实现代码逻辑与底层元素位置之间的解耦。

>>> from collections import namedtuple
>>> Sub=namedtuple('Subscriber',['addr','joined'])
>>> subscriber=Sub('lucy@example.com','2016-8-7')
>>> subscriber
Subscriber(addr='lucy@example.com', joined='2016-8-7')
>>> subscriber.addr
'lucy@example.com'
>>> subscriber.joined
'2016-8-7'

命名元组namedtuple的实例与普通元组完全兼容,支持所有标准元组操作,包括索引访问和序列解包(unpacking)。

>>> len(subscriber)
2
>>> addr,joined=subscriber
>>> addr
'lucy@example.com'
>>> joined
'2016-8-7'
>>>

以下是使用普通元组的代码示例:

def compute_cost(records):
  total = 0.0
  for rec in records:
    total += rec[1] * rec[2]
  return total

仅通过位置索引引用元素会导致代码可读性较差,且紧密耦合于数据结构的具体定义,一旦结构变化,所有引用处均需修改。

以下是使用命名元组重构后的代码版本:

# example.py
from collections import namedtuple
Stock = namedtuple('Stock', ['name', 'shares', 'price'])
def compute_cost(records):
  total = 0.0
  for rec in records:
    s = Stock(*rec)
    total += s.shares * s.price
  return total
# Some Data
records = [
  ('GOOG', 100, 490.1),
  ('ACME', 100, 123.45),
  ('IBM', 50, 91.15)
]
print(compute_cost(records))

程序运行输出结果如下:

65912.5

补充说明:

在构建涉及字典的大型数据结构时,使用namedtuple通常比直接使用字典更高效。但需注意,namedtuple实例是不可变的。例如尝试直接修改属性会引发错误:

>>> s=Stock('ACMS',100,123.45)
>>> s
Stock(name='ACMS', shares=100, price=123.45)
>>> s.shares=75
Traceback (most recent call last):
 File "<pyshell#2>", line 1, in <module>
  s.shares=75
AttributeError: can't set attribute
>>>

若需修改属性值,应使用命名元组实例的_replace()方法。该方法不会原地修改,而是创建一个新的命名元组实例,并将指定字段的值替换为新值。

>>> s=s._replace(shares=75)
>>> s
Stock(name='ACMS', shares=75, price=123.45)
>>>

_replace()方法还有一个巧妙用法:它可以作为填充具有可选或缺失字段的命名元组的便捷手段。

具体操作步骤如下:

首先,创建一个包含默认值的“原型”元组实例;

然后,利用_replace()方法创建新实例,通过传入字典参数将特定值替换到对应字段中;

from collections import namedtuple
Stock = namedtuple('Stock', ['name', 'shares', 'price','date','time'])
#创建一个包含默认值的“原型”元组
stock_prototype=Stock('',0,0.0,None,None)
#创建一个函数实现将字典转化为Stock类型
def dict_to_stock(s):
  return stock_prototype._replace(**s)
a={'name':'ACMS','shares':100,'price':123.45}
print(dict_to_stock(a))
b={'name':'ACMS','shares':100,'price':123.45,'date':'2016-08-08'}
print(dict_to_stock(b))
c={'name':'ACMS','price':123.45}
print(dict_to_stock(c))

运行上述代码的输出结果如下:

Stock(name='ACMS', shares=100, price=123.45, date=None, time=None)
Stock(name='ACMS', shares=100, price=123.45, date='2016-08-08', time=None)
Stock(name='ACMS', shares=0, price=123.45, date=None, time=None)

注意:如果设计目标是定义高性能数据结构,且预期未来需要频繁修改各个实例的属性,那么不建议使用namedtuple,应考虑使用字典或其他可变数据结构。

(相关代码示例摘自《Python Cookbook》)

感兴趣读者可进一步查阅本站相关专题:《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》。

希望本文关于Python程序设计的阐述能对大家有所帮助。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。