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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Python 中,yield 语句用于在函数中生成。这意味着,当调用这个函数时,它并不会立即执行函数内的代码,而是返回一个对象,可以用于遍历函数内部生成的数据。 举个例子,假设我们想要写一个函数来生成从 0 开始的无限整数序列。我们可以这样做: ``` def infinite_sequence(): i = 0 while True: yield i i += 1 ``` 调用这个函数时,它并不会生成整个序列,而是返回一个对象,可以用于遍历序列。比如,我们可以使用 for 循环遍历这个序列: ``` for i in infinite_sequence(): print(i) ``` 这个代码会打印出从 0 开始的无限整数序列。 还有一点需要注意,当你在函数中使用 yield 语句时,这个函数就成为了一个生成器(generator)。与普通函数不同的是,生成器只会在被请求时执行代码,而不是立即执行。 如果你想了解更多关于 Python 中 yield 语句的知识,可以参考 Python 官方文档中的这篇文章:https://docs.python.org/3/tutorial/introduction.html#generators ### 回答2: 在Python中,yield是使用生成器的关键字。是一个特殊的对象,它可以在每次调用next()函数时返回一个值,直到没有值可返回时抛出StopIteration异常。当使用yield语句时,函数变成了一个生成器函数。 生成器函数使用yield语句产生结果。当函数执行到yield语句时,它会挂起并返回yield后面的值,并保存函数的当前状态,以便下次调用时从yield语句的下一行代码开始执行。每次调用生成器函数时,它都会继续执行,直到再次遇到yield语句。 以下是一个示例,展示了如何使用yield创建一个简单的生成器: ```python def countdown(n): while n > 0: yield n n -= 1 # 创建一个对象 c = countdown(5) # 使用next()函数获取生成器的下一个值 print(next(c)) # 输出: 5 # 使用for循环遍历生成器的所有值 for i in c: print(i) # 输出: 4, 3, 2, 1 ``` 在上述示例中,countdown函数是一个生成器函数,使用yield语句返回一个值n,并且保留了函数的状态。通过调用countdown函数并将返回的生成器对象赋值给变量c,我们可以使用next(c)函数来获取生成器的下一个值。在for循环中,我们可以直接使用c来遍历所有返回的值。 总结来说,yield的使用方法是在生成器函数中使用yield语句来产生结果。每次调用生成器函数时,函数都会从上次挂起的位置继续执行,直到再次遇到yield语句。通过的方式,我们可以方便地按需产生数据,而不是一次性生成所有数据。 ### 回答3: 在Python中,是一个对象,用于遍历可代对象(如列表、元组、字符串等)中的元素。而`yield`是Python中用于创建的关键字。 使用`yield`关键字可以将一个函数转换为生成器函数。生成器函数是一种特殊的函数,它可以在遍历过程中暂停和恢复执行。当生成器函数被调用时,它返回一个对象,可以通过循环语句遍历生成器的每个元素。 下面是一个简单的使用`yield`的例子: ```python def my_generator(): yield 1 yield 2 yield 3 # 调用生成器函数,返回一个对象 my_iterator = my_generator() # 使用循环语句遍历的每个元素 for num in my_iterator: print(num) ``` 以上代码定义了一个`my_generator`生成器函数,它通过`yield`关键字依次返回1、2、3三个元素。在调用生成器函数时,会返回一个对象`my_iterator`。我们可以使用`for`循环遍历对象,并逐个打印生成器函数中的元素。 运行以上代码,输出结果为: ``` 1 2 3 ``` 这说明`yield`关键字使得函数变成了生成器函数,并且可以通过循环语句遍历生成器函数中的每个元素。 需要注意的是,生成器函数在每次使用`yield`关键字返回一个值后会暂停执行,直到下一次调用`next()`函数时才会继续执行。这使得生成器函数具有延迟计算的特性,可以节省内存和计算资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值