Python系列教程
第1章 Python 语言概述
Python编程规范+最佳实践
python文件:.py,.ipynb, pyi, pyc, pyd, pyo都是什么文件?
第1章必背的内容
第2章 Python基础
字符串切片
Python数据类型大战:可变与不可变,谁主沉浮?
Python「布尔类型」:不只是True和False!
Python「枚举类型」:你真的了解枚举类型吗?
Python字符串格式化:哪种字符串格式化方法最快?
Python字符串编码:为什么你的网页显示乱码?
Python「内置变量」:不只是变量,更是编程的魔法!
Python变量的作用域,你真的了解吗?
Python中如何使用F-Strings格式化浮点数
第2章必备的内容
第3章 流程控制和异常处理
加速Python for循环
for循环
Python三元表达式:让代码简洁与效率提升成为可能
Python「While循环」:何时打破循环?
Python「异常处理」:程序出错了?不慌
这样可以减少IF语句的使用,从此告别if-else噩梦
Python循环加速的秘方,可提速上千倍!
如何在Python中优雅地使用断言?这篇文章给你答案!
Python异常处理:12个异常处理技巧,你掌握了几个?
Python中的and和or你真的会用吗,代码逻辑竟然可以如此简单!
Python的else子句7个妙用,原来还能这样用,整挺好!
快来看!Python写代码,没有pass怎么行?
第三章 必背的内容
第4章 高级数据结构
Python字典嵌套:编程界的俄罗斯套娃
Python「类型注解」:如何让你的Python代码够清晰?
列表越界了?来学学Python列表的花式操作!
Python字典的这些黑科技,你用过几个?
Python元组:为何你的代码需要这个'不变'的伙伴?
试试Python具名元组NamedTuple吧!用过的都说好
Python中的5种队列数据结构,你知道几个?
itertools模块让你的代码原地起飞!
第5章 正则表达式
正则表达式
本文档使用 MrDoc 发布
-
+
首页
试试Python具名元组NamedTuple吧!用过的都说好
# 1、基础用法:直接定义 NamedTuple 🌟 ## 1.1 什么是NamedTuple 在Python中,NamedTuple是一种特殊形式的元组,它为元组内的每个元素赋予了名字,从而使得访问更加直观且代码更具自解释性。这种数据结构结合了元组的不可变性和字典的键值对应特性,非常适合用来表示具有固定属性的小型对象集合,比如数据库查询结果、配置项等。 ## 1.2 创建NamedTuple类型 创建NamedTuple类型通常通过typing.NamedTuple类完成。下面展示如何定义一个简单的Point类型来表示二维坐标点: from typing import NamedTuple class Point(NamedTuple): x: float y: float # 实例化NamedTuple p = Point(3.0, 4.0) 1.3 访问与修改元素 由于NamedTuple是不可变的,一旦创建后其内容就不能更改。访问元素就像访问普通元组一样 ,但可以通过属性名进行 ,这大大增强了代码的可读性: print(p.x) # 输出: 3.0 print(p.y) # 输出: 4.0 # 注意:不能对NamedTuple的属性进行赋值操作,如p.x = 5会引发AttributeError 通过这种方式,NamedTuple不仅提供了清晰的数据结构表示 ,还保证了数据的安全性,防止了意外的修改。在需要表示不可变的、具有特定意义的数据组合时 ,它是首选的数据结构之一。 2、进阶技巧:继承与扩展 🌱 2.1 继承NamedTuple 尽管NamedTuple默认是不可变的,但通过继承,我们可以为其添加行为,甚至扩展额外的字段。下面演示如何从基础NamedTuple派生出一个新的类,并添加方法: from typing import NamedTuple class BasePoint(NamedTuple): x: float y: float class ColorPoint(BasePoint): color: str = 'black' def __str__(self): return f"Point({self.x}, {self.y}, color={self.color})" # 实例化并打印ColorPoint cp = ColorPoint(3.0, 4.0, 'red') print(cp) # 输出: Point(3.0, 4.0, color=red) 在这个例子中 ,ColorPoint继承自BasePoint,并新增了一个字段color ,同时重写了__str__方法以提供更友好的字符串表示。 2.2 扩展字段与方法 除了简单地添加字段,我们还可以利用类方法或静态方法来扩展功能,比如实现一些计算逻辑或验证规则: class DistancePoint(ColorPoint): def distance_to_origin(self): """计算点到原点的距离""" return (self.x ** 2 + self.y ** 2) ** 0.5 @classmethod def from_polar(cls, radius: float, angle_deg: float, color='black'): """从极坐标创建点实例""" x = radius * cos(radians(angle_deg)) y = radius * sin(radians(angle_deg)) return cls(x, y, color) # 使用新方法 dp = DistancePoint(3, 4, 'blue') print(dp.distance_to_origin()) # 输出: 5.0 # 从极坐标创建点 polar_point = DistancePoint.from_polar(5, 45) print(polar_point) # 输出取决于具体坐标转换 通过这些进阶技巧 ,NamedTuple不仅能保持数据的纯净性和不可变性,还能通过继承和扩展,变得更加灵活和强大,适用于更广泛的场景。 3、实战应用:数据结构优化 🔄 3.1 替代dict和list场景 在处理结构化数据时,如果数据具有固定的字段且不需要动态增减,NamedTuple相比dict和list有显著优势。例如,在表示数据库记录或API响应结构时: from typing import NamedTuple class User(NamedTuple): id: int username: str email: str # 使用NamedTuple代替dict user_dict = {'id': 1, 'username': 'Alice', 'email': 'alice@example.com'} user_namedtuple = User(id=1, username='Alice', email='alice@example.com') # 直观访问属性优于键值查找 print(user_namedtuple.username) # 更直接的访问方式 3.2 提升代码可读性 由于NamedTuple成员有明确的命名,可以显著提升代码的可读性和维护性,特别是在大型项目中。例如,处理日志条目时: class LogEntry(NamedTuple): timestamp: float level: str message: str log = LogEntry(1623456000.0, 'INFO', 'Application started.') # 易于理解的属性访问 if log.level == 'ERROR': print(f"Error at {log.timestamp}: {log.message}") 3.3 与其他数据结构对比 • 与dict对比:NamedTuple提供了字段名的同时保持了元组的不可变性,使得数据更安全,适合存储不需要修改的结构化信息。而dict允许动态添加和删除键值对,适合更多变的数据结构。 • 与list对比:列表适合存储有序但无固定结构的数据集合。当集合中的每个元素都具有相同的结构和语义时,NamedTuple则更加合适,因为它提供了类型安全和更清晰的访问方式。 • 性能考量:虽然直接比较性能可能因具体应用场景而异,NamedTuple通常比同等大小的dict占用更少的内存,因为它们不需要存储键的哈希表。此外 ,访问 NamedTuple 的属性通常比访问 dict 的键更快。 通过这些实战应用 ,可以看到NamedTuple在特定场景下能有效优化数据结构,提高代码的清晰度和运行效率,是Python编程中不可或缺的高级特性之一。 4、高级特性:类型注解与模式匹配 🎯 4.1 类型注解的运用 Python 3.5 引入了类型注解,而NamedTuple与类型注解的结合能够增强代码的自我文档化能力及静态检查的可能性。通过在定义NamedTuple时指定字段类型 ,可以明确预期的数据类型,辅助IDE和类型检查器提供更好的代码补全和错误提示: from typing import NamedTuple class InventoryItem(NamedTuple): name: str quantity: int unit_price: float item = InventoryItem(name='Widget', quantity=10, unit_price=49.99) 上述代码中,name、quantity和unit_price字段分别指定了字符串、整数和浮点数类型,提高了代码的清晰度和维护性。 4.2 利用match case模式匹配 Python 3.10 引入的match-case语句为处理不同类型的值提供了更优雅的方式,尤其适合与NamedTuple配合使用。通过模式匹配,可以针对NamedTuple的不同字段值编写分支逻辑: def process_item(item: InventoryItem): match item: case InventoryItem(name='Widget', quantity=q, unit_price=p): print(f"Processing Widget with quantity {q} at ${p:.2f} each.") case InventoryItem(quantity=q) if q > 50: print(f"Large order of {q} items detected!") case _: print("Handling general inventory item.") process_item(InventoryItem(name='Widget', quantity=75, unit_price=49.99)) 这里,match-case不仅检查了InventoryItem的类型,还进一步匹配了具体的字段值和条件,使得逻辑表达更为直接和简洁。通过模式匹配,代码可读性更强,维护成本更低。 5、性能考量:与普通元组的差异 🔍 5.1 内存占用分析 NamedTuple相比普通元组,在存储相同数据时会占用更多的内存。原因在于NamedTuple为了提供字段名访问的能力,内部需要额外存储类型信息和字段名。尽管这个开销对于单个实例来说微乎其微 ,但在处理大量数据时差异可能会变得明显。通过使用Python的内置函数sys.getsizeof(),可以大致评估两种结构的内存占用: import sys from collections import namedtuple Point = namedtuple('Point', ['x', 'y']) # 普通元组 plain_tuple = (1, 2) print(sys.getsizeof(plain_tuple)) # 输出内存占用 # NamedTuple实例 named_tuple = Point(x=1, y=2) print(sys.getsizeof(named_tuple)) # 输出内存占用 实际输出数值会依据Python版本和平台有所不同 ,但一般情况下,NamedTuple的内存占用会略高于相同内容的普通元组。 5.2 访问速度比较 尽管NamedTuple在内存占用上不占优势,但在访问速度上 ,尤其是在频繁访问的情况下,它通常表现得更为高效。这是因为通过属性访问(.x, .y)通常比索引访问([0], [1])更快速 ,尤其是在现代解释器中 ,属性访问往往经过优化。 为了量化这一差异,可以通过简单的计时测试来比较: import timeit def access_plain_tuple(): global plain_tuple _sum = plain_tuple[0] + plain_tuple[1] def access_named_tuple(): global named_tuple _sum = named_tuple.x + named_tuple.y # 执行时间测试 print(timeit.timeit(access_plain_tuple, number=1000000)) print(timeit.timeit(access_named_tuple, number=1000000)) 注意 ,实际的测试结果可能受多种因素影响,包括但不限于Python解释器版本、操作系统、CPU性能等。但一般趋势是,对于字段访问密集型操作 ,NamedTuple的属性访问机制可能会带来性能上的小幅度提升。 综上所述 ,在选择NamedTuple还是普通元组时,应当根据具体的应用场景权衡内存消耗与访问效率的需求。对于追求代码可读性和维护性的场景,NamedTuple的额外开销通常是值得的;而在对内存敏感的大规模数据处理场景,则可能需要更细致地考虑。 6、总结:何时何地选择NamedTuple 🚀 NamedTuple作为Python中一种高效数据结构,通过命名字段提升了元组的可读性和实用性。本文深入探讨了其基础定义、进阶继承扩展、实战应用优化、类型注解与模式匹配的高级用法,以及与普通元组的性能对比。选择NamedTuple,尤其在需要不可变数据、明确结构与类型安全的场景 ,能显著增强代码的清晰度与维护性。尽管内存占用相对较高,其带来的代码可读性和属性访问效率优势,使之成为数据处理、配置表示等领域的优选工具。掌握NamedTuple ,是在Python项目中平衡代码质量与性能的明智之举。
张泽楠
2024年6月15日 16:51
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码