python-迭代器和生成器

可迭代对象

  • 从集合的第一个元素开始访问,直到所有的元素被访问完结束,即可以被for循坏遍历
  • 需要实现__iter__ 或者 __getitem__方法
from collections.abc import Iterator,Iterable
class testIter():
    def __init__(self):
        pass
    def __iter__(self):
        pass
print(isinstance(testIter(),Iterable))   #输出 True  ,说明时可迭代对象
print(isinstance(testIter(),Iterator))  #输出 False ,说明不是迭代器

迭代器

  • 遵循迭代器协议的对象
  • 迭代器协议:实现__iter__ 和 __next__方法,方法放回迭代器本身,next()方法返回容器的下一个元素
  • 迭代器如果没有后续元素,访问时会抛出StopIteration异常,只能往前访问不能后退
  • 迭代器是一个可以记住遍历的位置的对象
  • 使用iter()可以获取迭代器对象

迭代器实现

  • 对可迭代对象使用,iter方法
from collections.abc import Iterator,Iterable
print(isinstance(iter(str()),Iterable))   #输出True
print(isinstance(iter(str()),Iterator))   #输出True
  • 实现__iter__和__next__方法,实现为迭代器
from collections.abc import Iterator,Iterable
    def __init__(self, data):
        self.data = data
        self.index = len(data)

    def __iter__(self):
        return self

    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]
var=testIter('abc')     
print(isinstance(var,Iterable))   #输出 True  ,说明时可迭代对象
print(isinstance(var,Iterator))  #输出 True ,说明是迭代器
print(isinstance(str(),Iterable))   #输出True
print(isinstance(str(),Iterator))   #输出False

next方法依次访问元素

访问testIter(‘abc’)迭代器

print(next(var)) #输出 c
print(next(var))  #输出 b
print(next(var))  #输出 a
print(next(l))  #报异常 StopIteration

#或者通过for循环访问
for i in var:
	print(i)

生成器

  • 是一种特殊的迭代器
  • 可以使用next和send取值,不同的是,send在获取下一个元素时可以同时向生成器传递一个值,next和send(None)等同

生成器实现

使用yeild关键字

yeild:与return功能相似,会返回一个值,但是遇到yeild的时候函数会暂停并保存当前的运行信息,下次执行next/send方法时会继续执行
生成器优点:不需要将所有数据一次性都加载到内存中,对于需要的数据才进行访问

def testGene(n):
    for i in range(n):
        if i % 2 == 0:
            yield str(i) * 5
            print('abc')
g=testGene(10)
print(next(g))    #执行这一步输出  00000
print(next(g))   #执行这一步输出 abc 
                 #               22222  可以看出第一次执行到yield时就停止了,再次调用next方法时,继续执行print('abc')
  • next和send方法的区别
    还是以上例子通过send方法调用
print(g.send(None))  #第一次访问,send的参数必须是None  输出 00000
print(g.send('send1'))  #执行这一步输出 abc 
                 #               22222
print(g.send('send2'))   #执行这一步输出 abc 
                 #               44444

可以看出send传递的值没有生效,需要修改一下生成器的实现

def testGene(n):
    for i in range(n):
        if i % 2 == 0:
            x=yield str(i) * 5   #接收send传递的值
            yield x
            print('abc')

g=testGene(10)
print(g.send(None))  #输出00000   (执行到第一个yield暂停,并返回00000)
print(g.send('send1')) #输出send1  (继续执行x='send1',遇到第二个yield,并返回'send1')
print(g.send('send2')) #执行这一步输出 abc  (继续执行print,遇到生成器中的第一个yield,并返回22222
                 #               22222
print(g.send('send3'))  #输出send3     (执行x='send3',遇到生成器中的yield并返回send3
print(next(g))  #执行这一步输出 abc  (继续执行print,遇到生成器中的第一个yield,并返回44444
                 #              44444

使用生成器表达式

区别列表推导式,列表推导式使用的[],生成器使用的()

from collections.abc import Iterator,Iterable,Generator
var=(x for x in range(10) if x%2==0)
print(isinstance(var,Iterator))  # 输出True
print(isinstance(var,Generator))   # 输出True,说明var时一个生成器
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值