python生成器和迭代器理解_Python知识点-生成器和迭代器

1.先了解下列表生成式

有一个列表[1,2,3,4,5,6,7,8,9],对没一个元素都进行*2

#通用做法是用lamba

ret = map(lambda x:x*2,[1,2,3,4,5,6,7,8,9])#python3 得到的ret 是一个map对象,在通过for循环得到#python2 得到的事一个列表不需要再次for循环

print(ret) #

for i inret:print(i)#通过列表生成式直接生成一个列表

ret = [x*2 for x in [1,2,3,4,5,6,7,8,9]]

2.什么是生成器?

通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的,而且创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,就会浪费大量的内存空间。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间,在Python中,这种一边循环一边计算的机制,称为生成器:generator

生成器是一个特殊的程序,可以被用作控制循环的迭代行为,python中生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,而可以使用next()函数和send()函数恢复生成器。

3.python中的生成器,生成器表达式:返回一个对象,这个对象只有在需要的时候才产生结果

#要创建一个generator,有很多种方法,第一种方法很简单,只有把一个列表生成式的[]中括号改为()小括号,就创建一个generator

#列表生成式

lis = [x*x for x in range(10)]print(lis)#生成器

generator_ex = (x*x for x in range(10))print(generator_ex)

结果:

[0,1, 4, 9, 16, 25, 36, 49, 64, 81] at 0x000002A4CBF9EBA0>

#得到的结果也不一样,一个是列表一个是对象,那么如何打印出generator_ex的每一个元素呢?通过generator_ex.__next__()或者next(generator_ex)

结果:

01

4

9

16

25

36

49

64

81Traceback (most recent call last):

File"列表生成式.py", line 42, in

print(next(generator_ex))

StopIteration#到最后一个元素后,再次调用__next__() 会触发 StopIteration error,代表已经没有元素了,这种感觉很不好,所以一般我们使用for 循环拿就不会触发error,因为generator也是可迭代对象

for i ingenerator_ex:print(i)

3.生成器函数使用以斐波那切数列举例,从第3项开始,每一项都等于前两项之和。1 1 2 3 5 8 13 21 34......

生成器函数:也是用def定义的,利用关键字yield一次性返回一个结果,阻塞,重新开始

#斐波那契数列,普通函数形式

deffib(number):

n=0

a,b=0,1

while n

a,b=b,a+b

n=n+1

print(a)return ('done')

a= fib(10)print(a)#通过生成器实现,每次调用__next__() 都会yield d 拿到b 这个值,然后继续循环到yiled b停住,继续监听有没有next调用

deffib(number):

n=0

a,b=0,1

while n

a,b=b,a+b

n=n+1

return('done')

f=fib(3)#通过for循环拿不到return值

for i inf:print(i)#结果:

1

1

2

3

5

8

13

21

34

55

#要是想得到return 返回值就需要__next__()通过try except获取异常

deffib(number):

n,a,b=0,0,1

while n

a,b=b,a+b

n= n+1

return('done')

g= fib(6)whileTrue:try:

x= __next__(g)print('generator:',x)exceptStopIteration as e:print("生成器返回值:",e.value)break结果:

generator:1generator:1generator:2generator:3generator:5generator:8生成器返回值: done

4. 生成器 send 用法

defgenerator():whileTrue:

receive= yield 1

print('hahaha' +str(receive))yield 2g=generator()print(next(g)) #一定要先next一次后再send值,不然会报错

print(g.send('ok')) #send ok 给receive接收,receive = yield 1 这句就代表结束了,然后遇到下一次的yiled断点 返回yiled的值#print(next(g))

#结果:

1hahaha ok2

1

5.通过 generator yiled 来实现协程,标准的生产者-消费者模型

importtimedefconsumer():

r= ''

whileTrue:

r= '我饿了'n= yield r #这个n 是生产者发送过来的n 不是r 这个值

print(n)if notn:return

print('[消费者] 消费了 %s 个大包子...' %n)#time.sleep(1)

#c = consumer()#print(c.__next__())#print(c.send('a'))

defproduce(c):#消费者调用next 准备send包子

print(c.__next__())

n=0#设定生产几个包子

while n < 5:

n= n + 1

print('[生产者] 生产了 %s 个大包子...' %n)

r= c.send(n) #send给 消费者 并且接收了yiled '我饿了'

if r == '我饿了':print('[生产者] 消费者说真他妈好吃啊')else:print('[生产者] 消费者说狗都不想吃')

c.close()if __name__=='__main__':

c= consumer() #消费者实例

produce(c)#结果:

我饿了

[生产者] 生产了1个大包子...

[消费者] 消费了1个大包子...

[生产者] 消费者说真他妈好吃啊

[生产者] 生产了2个大包子...

[消费者] 消费了2个大包子...

[生产者] 消费者说真他妈好吃啊

[生产者] 生产了3个大包子...

[消费者] 消费了3个大包子...

[生产者] 消费者说真他妈好吃啊

[生产者] 生产了4个大包子...

[消费者] 消费了4个大包子...

[生产者] 消费者说真他妈好吃啊

[生产者] 生产了5个大包子...

[消费者] 消费了5个大包子...

[生产者] 消费者说真他妈好吃啊

6.迭代器

迭代器就是循环,并且可以用next调用

可迭代对象Iterable不一定是Iterator迭代器,但是迭代器一定时可迭代对象。

生成器都是迭代器Iterator,但list、dict、str虽然是Iterable(可迭代对象),却不是Iterator(迭代器),可以使用for 循环的都是可迭代对象。

#判断是否为可迭代对象

>>> from collections importIterable>>>isinstance([], Iterable)

True>>>isinstance({}, Iterable)

True>>> isinstance('abc', Iterable)

True>>> isinstance((x for x in range(10)), Iterable)

True>>> isinstance(100, Iterable)

False#也可以使用isinstance()判断一个对象是否是迭代器Iterator对象:

>>> from collections importIterator>>> isinstance((x for x in range(10)), Iterator)

True>>>isinstance([], Iterator)

False>>>isinstance({}, Iterator)

False>>> isinstance('abc', Iterator)

False#可以使用iter()变成迭代器对象

>>>isinstance(iter([]), Iterator)

True>>> isinstance(iter('abc'), Iterator)

True>>> a=[1,2,3,4]>>> b=iter(a)>>> print(b)

>>> b.__next__()1

>>> b.__next__()2

>>> b.__next__()3

>>> b.__next__()#要判断一个对象是不是迭代器 可以直接用next方法调用,或者用isinstance(对象,Iterator)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值