17. 对迭代器进行切片
例如, 有某个文本文件,想读取其中某范围的内容,如100 ~ 300行之间的内容,python中文件是可迭代对象。
要求:使用类似列表切片的方式得到一个100 ~ 300行文件内容的生成器。
解决方案:
使用itertools.islice()
函数,它能返回一个迭代对象切片的生成器。
对于列表切片:
l = list(range(10))
l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]l[3]
3l[2:8]
[2, 3, 4, 5, 6, 7]l[2
2]
[2, 4, 6]l.getitem(3)
3l.getitem(slice(2, 8))
[2, 3, 4, 5, 6, 7]l.getitem(slice(2, 8, 2))
[2, 4, 6]
在Python中对list引用元素和形式优雅简洁的切片操作都是由解释器调用的list.__getitem__()
特殊方法。
对于取单个值,list[x]
等同于list.__getitem__(x)
;对于切片,list[start, end, step]
等同于list.__getitem__(slice(start, end, step))
,默认step为1。
对于
itertools.islice()
函数:itertools.islice(iterable, start, stop[, step])
创建一个迭代器,返回从iterable
里选中的元素。如果start
不是0,跳过iterable
中的元素,直到到达start
这个位置。之后迭代器连续返回元素,step默认为1,除非step设置的值很高导致被跳过。
如果stop
为 None,迭代器耗光为止;否则会在指定的位置停止。与普通的切片不同,islice()
不支持将start
、stop
或step
设为负值。
对于
enumerate()
函数:enumerate(iterable, start=0)
l = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’]
list(enumerate(l))
[(0, ‘a’), (1, ‘b’), (2, ‘c’), (3, ‘d’), (4, ‘e’)]
enumerate()
函数返回一个枚举对象。iterable
必须是一个序列,或迭代器,或其他支持迭代的对象。
enumerate()
返回的迭代器的__next__()
方法返回一个元组,里面包含一个计数值(从start开始,默认为0)和通过迭代iterable
获得的值。
方案示例:
from itertools import islice
f = open(‘/var/log/messages’)
for line in islice(f, 100-1, 300): #islice()默认从0开始计数
print(line)
如果是将文本文件通过readlines()
函数转换为列表,然后再通过列表切片读取其中部分内容,这样当文本文件很大时则会浪费大量内存。
相比之下,通过itertools.islice()
创建一个生成器进行切片截取文本文件的内容更合适简便。
实现简单的
my_islice()
函数:from itertools import islice
def my_islice(iterable, start, end, step=1):
tmp = 0
for i,x in enumerate(iterable):
if i >= end:
break
if i >= start:
if tmp == 0:
tmp = step
yield x
tmp -= 1
print(list(islice(range(50, 100), 10, 30, 3)))
print(list(my_islice(range(50, 100), 10, 30, 3)))[60, 63, 66, 69, 72, 75, 78] #结果
[60, 63, 66, 69, 72, 75, 78]
还没有评论,来说两句吧...