Python 高手编程系列三百九十五:namedtuple

namedtuple 是一个类工厂,它接受一个类型名称和一个属性列表,并从中创建一个
类。然后,该类可以用于实例化类似元组的对象,并为其元素提供访问器如下所示:

from collections import namedtuple
Customer = namedtuple(
… ‘Customer’,
… ‘firstname lastname’
… )
c = Customer(‘Tarek’, ‘Ziadé’)
c.firstname
‘Tarek’
它可以用于创建记录,这要比需要一些样板代码来初始化值的自定义类更容易编写。
另一方面,它是基于元组的,所以通过索引访问其元素非常快。生成的类可以被子类化以
添加更多的操作。
相比其他数据类型,最初使用 namedtuple 的增益可能不明显。主要的优点是,它比
普通元组更容易使用、理解和解释。元组索引不包含任何语义,因此通过属性访问元组元素,
这很棒。然而,你可以从具有 O(1)平均复杂度的 get/set 操作的字典中获得相同的好处。
在性能方面的第一个优点是 namedtuple 仍然具有元组的特点。这意味着它是不可变
的,所以底层的数组存储被精确地分配所需的大小。另一方面,字典需要使用内部散列表
的过度分配,以确保 get/set 操作的平均复杂度足够低。因此,namedtuple 在内存效率方面胜过字典。
实际上,namedtuple 是基于元组的,这可能也有益于它的性能。其元素可以通过整
数索引访问,类似于另外两个简单序列对象,即列表和元组。这个操作既简单又快速。在
字典或自定义类实例(也使用字典存储属性)的情况下,元素访问需要散列表查找。它是高度
优化的,以确保良好的性能与集合大小无关,但所提到的 O(1)复杂度实际上只是平均复杂性。
在字典中 set/get 操作的实际的均摊最坏情况复杂度是 O(n)。在给定时刻执行这样的操作时
的实际工作量取决于集合的大小及其来历。因此,在对性能至关重要的代码段中,使用列表或
元组而不是字典,有时可能是明智的做法。这只是因为它们在性能方面更可预测。
在这种情况下,namedtuple 是一个很好的类型,它结合了字典和元组的优点。
• 在可读性更重要的部分,可能优先使用属性访问。
• 在性能关键部分,元素可以通过其索引访问。
架构体系的权衡
当不能通过降低复杂度或选择合适的数据结构进一步改善你的代码的时候,一个好的
方法可能是考虑做一些权衡。如果我们回顾用户问题并定义对他们真正重要的内容,我们
可以放宽一些应用程序需求。通常可以通过以下方式提高性能。
• 使用启发式算法和近似算法替换精确求解算法。
• 将一些工作推迟到延迟任务队列中处理。
• 使用概率性的数据结构。
使用启发式和近似算法
一些算法问题根本没有在运行时间上可以让用户接受的技术解决方案。例如,考虑一
个程序处理一些复杂的优化问题,如旅行推销员问题(TSP)或车辆路径问题(VRP)。这
两个问题是组合优化中的 NP-hard 问题。用于具有低复杂度的此类问题的确切算法是未知的。这意味着可以实际解决的问题的规模会受到很大限制。对于非常大的输入,它将无法
很快地提供确切的解决方案,对任何用户来说,该方案在时间上是可接受的。
幸运的是,相比一些足够好的方案以及可以及时获得的解决方案,用户很可能对最佳
解决方案并不感兴趣。因此,每当他们提供质量可接受的结果时,使用启发式(heuristics)
或近似算法(approximation algorithms)是有意义的。
• 启发式通过交易最优性、完整性、准确性或速度的精度来解决给定的问题。它们专注
于速度,但与精确算法的结果相比,可能真的很难证明它们的解决方案的质量。
• 近似算法在理念上与启发式相似,但是与启发式算法不同的是,它具有可证明的解
决方案质量和运行时间界限。
例如,有已知良好的启发式和近似问题可以在合理的时间内解决非常大的 TSP 问题。
它们也有很高的概率产生只有 2%~5%的最优解的结果。
启发式的另一个好处是,它们并不总是需要为每个需要解决的新问题从头开始构建。
它们的高级版本,称为元启发式(metaheuristics),提供解决数学优化问题的策略,这些问
题不是具体问题,因此可以应用在许多情况下。一些流行的启发式算法包括以下几种。
• 模拟退火。
• 遗传算法。
• 禁忌搜索。
• 蚁群优化。
• 进化计算。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值