Day12 Python基础之生成器、迭代器(高级函数)(十)

 

 https://www.cnblogs.com/yuanchenqi/articles/5769491.html

1. 列表生成式

我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加三次方,你怎么实现?你可能会想到2种方式

1 a=[0,1,2,3,4,5,6,7,8,9]
2 b=[]
3 for i in a:
4     b.append(i+1)
5 a=b
6 print(a)
普通版本
 1 a=map(lambda x:x+1,range(10))
 2 print(a,type(a))
 3 for i in a:
 4     print(i)
 5 
 6 输出结果:
 7 <map object at 0x0272A4D0> <class 'map'>
 8 1
 9 2
10 3
11 4
12 5
13 6
14 7
15 8
16 9
17 10
文艺版本
 1 (1 2 t=[0,1]
 3 a,b=t
 4 print(a)
 5 print(b)
 6 输出结果:
 7 0
 8 1
 9 (210 t=[0,1,2]
11 a,b=t
12 print(a)
13 print(b)
14 输出结果:
15 ValueError: too many values to unpack (expected 2)
16 (317 t=[0,1]
18 a,b,cc=t
19 print(a)
20 print(b)
21 print(c)
22 输出结果:
23 ValueError: not enough values to unpack (expected 3, got 2)
小知识点 
 1 def f(n):
 2     return n**3
 3 a=[f(x) for x in range(10)]
 4 print(a,type(a))
 5 
 6 等价于
 7 a=[x**3 for x in range(10)]
 8 print(a,type(a))
 9 输出结果:
10 [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] <class 'list'>
装逼版本

2. 生成器(generator)

生成器的创建方式有两种:()和yield

 1 a=(x**3  for x in range(10))
 2 print(a,type(a))
 3 
 4 等价于
 5 def f(n):
 6     return n**3
 7 a=(f(x) for x in range(10))
 8 print(a,type(a))
 9 
10 输出结果:
11 <generator object <genexpr> at 0x02DC34B0> <class 'generator'>
简单生成器之()生成演示

生成器数据类型的变量指向的内存地址,根本就没有任何数据在内存中,也没有存储在任何地方。

(类比理解:列表是将数据存储在变量指向的内存空间的,这就相当于你冰箱里面放了十道菜,你想吃哪个就去拿,这是占用一定的空间的,为了解决这个问题,我们有了生成器,就好比你拥有了一个有脾气的厨师,让厨师给你现做现吃,做哪个你就吃哪个好了,在生成器s中可以用生成器内置方法s.__next__()或者python内置函数next(s)这个方法按顺序生成值,这取决于你生成器的本身的特性。建议使用next(s)

生成生成器对象里面的值

 1 a=(x*2 for x in range(10))
 2 print(a,type(a))
 3 print(a.__next__())
 4 print(next(a))
 5 print(next(a))
 6 print(next(a))
 7 输出结果:
 8 <generator object <genexpr> at 0x028B34B0> <class 'generator'>
 9 0
10 2
11 4
12 6
next()生成值

 注:生成器就是一个可迭代对象,迭代器也是可迭代对象

 1 a=(x*2 for x in range(4))
 2 print(a,type(a))
 3 
 4 for i in a:
 5     print(i)
 6 
 7 输出结果:
 8 0
 9 2
10 4
11 6
遍历生成器

注:(1)for循环可遍历可迭代对象,有__iter__方法的都是可迭代对象内部的方法,iter()是内置函数

(2)for循环遍历可迭代对象的三个步骤:

      • 调用可迭代对象的iter方法,返回一个迭代器对象
      • 不断调用迭代器的next方法
      • 处理stopiteration异常

while:

try:

i=next(generator)

except StopIteration

break

(3)当内存中的数据,没有变量引用的时候(即没有变量指向该内存地址),该数据就会被python的解释器当垃圾清除掉

 这样就算遍历生成器,也不会占用大量内存,因为i的指向一直在更新,没有被引用的数据就会被清除

1 def f():
2     print('Hello')
3     yield  1
4     print('Ok')
5     yield  2
6 g=f()
7 print(g,type(g))
8 输出结果:
9 <generator object f at 0x033634B0> <class 'generator'>
简单生成器之yield生成演示

注:没有yield就是普通的函数,有yeild,定义的函数f()就是一个生成器对象,有几个yield就相当于几道菜。

生成生成器对象里面的值

 1 def f():
 2     print('Hello')
 3     yield  1
 4     print('Ok')
 5     yield  2
 6 g=f()
 7 next(g)
 8 next(g)
 9 输出结果:
10 Hello
11 Ok
next()

注:

(1)每调用一次next(g),就执行一遍g函数,以yield为结束点,返回1(相当于return结束函数的运行),再执行一遍next(g),以上次的结束点为起点,继续执行g函数,并返回2

(2)可通过yield实现在单线程的情况下实现并发运算的效果,即伪并发,CPU切换速度特别快,以至于我们不觉得有切换这一过程

 1 def f():
 2     print('Hello')
 3     yield  1
 4     print('Ok')
 5     yield  2
 6 g=f()
 7 
 8 for i in g:
 9     print(i)
10 输出结果:
11 Hello
12 1
13 Ok
14 2
for循环遍历生成对象

注:for循环遍历生成对象g,以yield结束标志执行函数内容,并打印出了yield返回值

 1 def fibo(N):
 2     Max=N
 3     n,before,after=0,0,1
 4     while n<Max:
 5         # print(after)
 6         yield after
 7         before,after=after,before+after
 8         n+=1
 9 g=fibo(8)
10 # print(next(g))
11 # print(next(g))
12 # print(next(g))
13 for i in g:
14     print(i)
yield生成斐波那契数列 

 生成器对象的send方法 

 1 def fibo(N):
 2     Max=N
 3     n,before,after=0,0,1
 4     while n<Max:
 5         # print(after)
 6         count=yield after
 7         print(count)
 8         before,after=after,before+after
 9         n+=1
10 g=fibo(8)
11 
12 g.send(None)    #相当于next(g),先进入生成器对象,遇到yield,返回after后结束
13 g.send('eee')   #从上一次结束点开始,继续程序,将send的参数赋值给count,继续执行后面的语句,直到再次遇到yield
14 输出结果:
15 eee
send方法传参数

注:进入生成器后(next,send(None))再能send传参数

3. 迭代器(iterator)

生成器都是迭代器,迭代器不一定是生成器;

可迭代对象(Iterable)不一定是迭代器(Iterator),通过iter方法可以把可迭代对象变成迭代器(迭代器对象),这是因为可迭代对象里面有__iter__方法。

什么是迭代器:需要满足两个条件:(1)有iter方法(2)有next方法

 1 from collections import Iterable,Iterator
 2 d=[1,2,3,4,5,6]
 3 a=iter(d)
 4 print(a,type(a))
 5 # print(next(a))
 6 # # print(next(a))
 7 # for i in a:
 8 #     print(i)
 9 print(isinstance(d,Iterable))    #判断d是不是可迭代对象
10 print(isinstance(d,list))    #判断d是不是列表
11 print(isinstance(d,Iterate))    #判断的是不是迭代器
迭代器

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/weinapang/p/9168388.html