字典——迭代和优化

未匹配的标注

如果上一节的for看起来像之前介绍过的列表理解表达式,这是应该的:它们两个都是真正的通用迭代工具。事实上,它们两个都适用于任何遵循迭代协议(在Python中所有迭代工具下的无处不在的理念)的可迭代对象。

简要地说,如果对象是在内存中的物理存储序列,或是在迭代操作(一种“虚拟”序列)上下文中每次生成一项的对象,那它就是可迭代的。更规范地,两种对象都被认为是可迭代的,因为它们支持迭代协议——它们以一个在响应next调用而向前推进的对象来响应iter调用,并当生成所有值后引发异常。

之前看到的generator理解表达式就是这种对象:它的值并不一次性存储在内存中,但按请求产生(通常是被迭代工具)。当Python文件对象被一个迭代工具使用时,是类似地逐行迭代:文件内容不是列表,它是按需获取的。在Python中,这两种都是可迭代对象——一个3.X中扩展的种类,来引入像rangemap这样的核心工具。

本书后面对迭代协议有更多论述。暂时记住每个从左到右扫描对象的Python工具都使用迭代协议。这是为什么在之前章节中使用的sorted调用直接适用于字典的原因——不必调用keys方法来获得一个序列,因为字典是可迭代对象,带有一个next返回连续的键。

它可能还帮助你认识到任何列表理解表达式(比如这个,它计算了一个数字列表的平方):

>>> squares = [x ** 2 for x in [1, 2, 3, 4, 5]]
>>> squares
[1, 4, 9, 16, 25]

总能被编码为for循环的等价物,在这个过程中用手动追加的方式构建起结果列表:

>>> squares = []
>>> for x in [1, 2, 3, 4, 5]: # 这是列表理解做的事情
                squares.append(x ** 2) # 内部都运行迭代协议
>>> squares
[1, 4, 9, 16, 25]

两个工具都在内部利用了迭代工具并产生了同样结果。然而,列表理解和相关的函数式编程工具如mapfilter 目前在一些类型的代码上都经常运行得比 for 循环更快(甚至可能快两倍)——对大数据集,这个属性在你的程序中可能很重要。然而,话虽如此,应该指出性能测量在Python中是很棘手的任务,因为它自身优化了很多,而且它们随版本不同而不同。

在Python中的一个经验法则是首先简单可靠地编码,在程序工作起来后,在已证明了有真正的性能问题后,再去担心性能。通常,代码会足够快而无需修改。然而,如果确实需要为性能而微调代码,Python包括了帮助你的工具,包括timetimeit模块用来测量替代方案的速度,还有profile模块用于隔离瓶颈。

本书后面和Python手册中有关于这些的更多知识(特别是见第21章的评分案例研究)。因为这只是预览,让我们前进到下一个核心数据类型。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~