博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python3 CookBook | 迭代器与生成器
阅读量:6761 次
发布时间:2019-06-26

本文共 2174 字,大约阅读时间需要 7 分钟。

本文首发于知乎专栏,欢迎关注。

以下测试代码全部基于 Python3。

反向迭代

想要反向迭代一个序列很容易,使用内置函数 reversed() 便可以做到,如下:

In [1]: a = [1, 2, 3, 4] In [2]: for x in reversed(a):   ...:     print(x)   ...:4321复制代码

反向迭代的特点是,需要预先知道迭代对象的大小,或者对象实现了 __reversed__() 方法,如果两者都不符合,那么,必须先将对象转换成一个列表才可以。

# Print a file backwardsf = open('somefile')for line in reversed(list(f)):    print(line, end='')复制代码

有一个需要注意的问题就是,如果迭代对象元素很多的话,在转换成列表的过程中会耗费大量的内存。

想解决这个问题,可以在自定义类上实现 __reversed__() 方法来解决,代码如下:

#!/usr/bin/env python#-*- encoding: utf-8 -*- def reverse_iterate(): 	for rr in reversed(Countdown(30)):		print(rr)	for rr in Countdown(30):		print(rr) class Countdown:	def __init__(self, start):		self.start = start 	    #  Forward iterator    def __iter__(self):		n = self.start		while n > 0:			yield n			n -= 1	# Reverse iterator 当使用reversed函数翻转对象时调用	def __reversed__(self):		n = 1		while n <= self.start:			yield n			n += 1  if __name__ == '__main__':	reverse_iterate()复制代码

这个方法可以使代码非常的高效,因为它不再需要将数据填充到一个列表中,然后再去反向迭代这个列表。

迭代器切片

在处理列表相关问题时,使用切片操作非常方便,但遗憾的是,迭代器并不支持标准的切片操作,主要原因就是因为,我们事先并不知道迭代器和生成器的长度。

In [3]: def count(n):   ...:     while True:   ...:         yield n   ...:         n += 1   ...: In [4]: c = count(0) In [5]: c[10: 20]-----------------------------------------------------------------------TypeError                                 Traceback (most recent call last)
in
()> 1 c[10: 20] TypeError: 'generator' object is not subscriptable复制代码

想在迭代器和生成器上使用切片操作,可以使用 itertools.islice() 函数:

In [6]: import itertools In [7]: for x in itertools.islice(c, 10, 20):   ...:     print(x)   ...:10111213141516171819复制代码

但是这里有一个问题,islice() 函数会消耗掉传入的数据,比如我再调用一次这个函数,返回的结果就发生了变化。

In [8]: for x in itertools.islice(c, 10, 20):   ...:     print(x)   ...:   ...:30313233343536373839复制代码

所以,如果想多次使用切片的结果,就需要把数据存起来。

顺序迭代合并后的排序迭代对象

假设现在有多个排序序列,现在想把它们合并,并且得到一个新的排序序列,应该怎么做呢?

heapq.merge() 函数可以完美解决这个问题:

In [9]: import heapq In [10]: a = [1, 4, 7, 10] In [11]: b = [2, 5, 6, 11] In [12]: heapq.merge(a, b)Out[12]: 
In [13]: for x in heapq.merge(a, b): ...: print(x) ...:1245671011复制代码

需要注意的一点是,传入的序列必须是排过序的。

如果序列中元素过多,也并不需要担心效率问题,通过上面代码也可以看出,heapq.merge() 函数的返回结果依然是一个生成器,并非是列表。

未完待续。。。

转载地址:http://zabeo.baihongyu.com/

你可能感兴趣的文章
深入解析Immutable及 React 中实践
查看>>
React 进阶二-组件最佳实践
查看>>
PHP的那些魔术方法(二)
查看>>
Android:使用 Intent 连接多个活动
查看>>
《设计模式》之代理模式
查看>>
【从 Spring 源码中学习设计原则or模式】- 0. 大纲
查看>>
AST语法结构树初学者完整教程
查看>>
「译」Web安全快速入门
查看>>
后台播放音乐时进来电话或微信视频通话暂停音乐播放 网易云音乐 喜马拉雅...
查看>>
弹性计算双周刊 第24期
查看>>
mysql 超大数据/表管理技巧
查看>>
常用Windows系统命令
查看>>
How to Properly Remove Datastore or LUN from ESXi 5.x hosts
查看>>
基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(二)
查看>>
json字符串和对象的转换
查看>>
好记性烂笔头3
查看>>
iptables的常见用法简述
查看>>
解决nat123之后速度慢的问题,使用javascript定时跳入带端口号的网址
查看>>
mybatis--foreach标签属性详解
查看>>
云计算学习规划
查看>>