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]
3

>>> l[2:8]
[2, 3, 4, 5, 6, 7]

>>> l[2:8:2]
[2, 4, 6]

>>> l.__getitem__(3)
3

>>> l.__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()不支持将startstopstep设为负值。

  • 对于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]    

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值