python制图一元迭代函数_python迭代器(3元表达式,列表生存式,生成器表达式,生成器函数)...

1.1迭代器

生么是迭代器:

迭代器是一个可以记住遍历的位置对象

迭代器对象从集合的第一个元素开始访问,直到所有元素被访问完结束,迭代器只能往前不能后退

迭代器有两个基本的方法:iter ,next 方法

内置函数iter() , next() 本质上都是对象.__init__(),  __next__()的方法

内置函数iter(iterable),表示把可迭代对象变成迭代器(iterator)

内置函数next(iterator) ,表示查看下一次迭代的值(当然也可以用 iterator.__next__() ,查看下一次迭代的值)

1.1.2迭代器协议

1.迭代器(iterator)协议是指:对象必须提供一共next方法,执行该方法妖魔返回迭代中的下一项,要么就引起一个Stopiteration异常,已终止迭代。

2.可迭代对象:实现了迭代器协议的对象,(该对象内部定义了一个__iter__()的方法  例:str.__iter__())就是可迭代对象

3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如。for循环,sum,min,max函数等)使用迭代器协议访问对象

1.1.3python中的for循环

for循环本质:循环所有对象,全部是使用迭代器协议

(字符串,列表,元祖,字典,集合,文件对象),这些都不是可迭代对象,只不过在for循环,调用了他们内部的__iter__方法,把他们变成了可迭代对象。然后for循环调用可迭代对象的__next__方法去去找,然后for循环会自动捕捉StopIteration异常,来终止循环。

l1 = ["hello","world",1,2]2

3#for循环调用可迭代对象的__next__方法去取值,而且for循环会捕捉StopIteration异常,以终止对象4 for i inl1:5print(i)6

7 aa = l1.__iter__() #等同于内置函数aa =iter(l1) 创建了一个list_iterator 列表迭代器8print(type(aa))9print(next(aa)) #内置函数 next()查看第一次迭代器的值10print(aa.__next__()) #迭代器本身对象的方法,第二次迭代器的值 跟 内置函数方法都是一样的11print(next(aa))12print(next(aa))13print(next(aa)) #没有可迭代的值了也就是迭代完了,会报错:StopIteration14

15

16#迭代器迭代完,就不能再次迭代该迭代器 比如for 循环17 for i inaa:18 print(i)

#首先获得Iterator对象:

2 it = iter([1, 2, 3, 4, 5]) #创建一个迭代器

3 #循环:

4 whileTrue:5 try:6 #获得下一个值:

7 x =next(it)8 print(x)9 exceptStopIteration:10 #遇到StopIteration就退出循环

11 break

总结:

1.可作用于for循环对象本身都是iterable(可迭代对象)类型,或者对象本身有obj.__iter__方法也是iterable

2.凡是可作用于next()函数的对象本身itertor(迭代器)类型,或者obj.__next__也是iterator ,迭代器是一个惰性序列

因为需要调用next,才会获得元素,迭代完,就不能再次迭代。

3.list、dict、str等是iterable,但不是iterator不过可以通过iter()函数获得一个迭代器对象

1.2生成器

什么是生成器?

1.从字面理解是不是:生成一个容器

2.在python中,一边循环,一边计算的机制,称为生成器(generator)。

3.可以理解为一种数据类型,这种类型自动实现了迭代器协议。(其他的数据类型需要调用自已的内置__iter__方法或则iter()的内置函数),所以生成器就是一个可迭代对象。

生成器分类以及在python中的表现形式。(python有两种不同的方式提供生成器)

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句的返回结果。yield语句一次返回一个结果,在每个结果中间,保留函数的状态,以便再上一次状态的重新执行。

2.生成器表达式:类似于列表推导,但是生成器返回按需产生结果的一种对象,而不是一次构建一个结果列表

为何使用生成器,生成器的优点:

python使用生成器对延迟操作提供了支持。所谓延迟操作,是指需要的时候才产生结果,而不是立即生成结果

这就是生成器的好处

生成器小结:

1.生成器是可迭代对象

2.实现了延迟计算,看内存(按需,执行)

3.生成器本质和其他类型一样,都是实现了迭代器协议,只不过生成器是一边计算,一边生成,从而节省内存空间,

其余的可迭代对象可没有好处。

定义生成器的前提:

1.考虑这个生成器是否需要多次遍历。

2.这个生成器内存空间的问题。

3.时间效率问题。

生成器是一个惰性的,根据惰性求值:也就是需要一个对象给一个对象

1.2.1生成器表达式、列表生成式、三元表达式

1.三元运算或则3元表达式

#三元表达式格式

2

3 res=值1 if 条件 else值24

5 #如果条件满足 res 等于 值1 条件不满足就等于 值2

6 #demo 1

7 name = "xixi"

8 res = "xixi" if name == "xixi" else "hello"

9 print(res)10

11 #demo 2

12 num = 2 if False else013 print(num)

列表生成式

#列表生成式通过计算生成一个列表

2

3 lis_gen = [ i for i in range(1,10)] #列表生成式

4 print(lis_gen)5

6 lis1_gen = [i for i in range(1,10) if i%2 == 0] #生成一个偶数的列表

7 print(lis1_gen)8

9 lis2_gen = [ i * i for i in range(1,10) if i%2 == 1] #生成以个奇数乘自已本身奇数的列表

10 print(lis2_gen)

3.生成器表达式

gen_exp = (i for i in range(10)) #生成器表达式

2 print(gen_exp) #generator

3 #for i in gen_exp: #取出生成器表达式的值,for循环

4 #print(i)

5 print(gen_exp.__next__()) #next方法

6 print(gen_exp.__next__())7 print(gen_exp.__next__())8 print(gen_exp.__next__())9 print(gen_exp.__next__())

1 gen = (i for i in range(10**100)) #生成器表达式

2 lis = [i for i in range(10**100)] #列表生成式

3

4 #生成器,更省内存,需要一个取一个

5 print(gen.__next__())6 print(lis) #需要在内存空间创建1-10**100序列

总结:

1.把列表解析的[]换成()得到就是生成器表达式

2.列表生成式式一个构建一个结果列表,生成器表达式:是返回按需产生结果的一个对象

3.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

4.python不但使用迭代器协议让for循环更加通用,大部分内置函数,也是使用迭代器协议访问对象的

如,sum函数是python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议

1.2.2生成器函数

在python中,使用了yield的函数就称为生成器(generator)

1.跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,可以理解为:生成器就是一个迭代器

2.在调用生成器运行过程中,每次遇到yield是函数会暂停并保存当前所有的运行信息,返回yield值。并在下一次执行next方法时,从当前位置继续运行。

普通生成器:

1 >>> gen = (i for i in range(5))

2 >>> gen

3 at 0x0000004DE29A70A0>

4 >>> next(gen)

5 0

6 >>> next(gen)

7 1

8 >>> next(gen)

9 2

10 >>> next(gen)

11 3

12 >>> next(gen)

13 4

14 >>> next(gen)

15 Traceback (most recent call last):

16 File "", line 1, in

17 StopIteration

注:generator保存的是算法,每次调用next方法,就计算出gen的下一个元素的值,直到计算到最后一个元素,没有更多元素时,就StopIteration的错误。

当然,上面这种不断调用next(gen),用着有点坑,正确的方法是使用for循环,因为generator也是iterator;

1 >>> g = (i for i in range(5))2 >>> for i ing:3 ... print(i)4...506 1

7 2

8 3

9 4

所以我们创建了一个generator后,基本不会调用next方法,而是通过for循环来迭代它,并且不是关心StopIteration的错误。

generator非常强大,如果计算的算法比较复杂,用for循环无法实现的时候,还可以用函数来实现。

例:斐波拉契数列 后面的一个数等于前面两个数相加的和

deffib(number):2 #得出几个斐波拉契数列

3 count,a,b = 0,0,1

4 while count <5 print a b count>

8 return "done"

9 fib(5)

1 deffib1(number):2 n,a,b = 0,0,1

3 while n<4 yieldb5 a b n>

7 return "done"

8 aa = fib1(6)9 print(aa) #generator

10 #print(aa.__next__())

11 for i inaa:12 print(i)

注:如果一个函数定义中包含yield关键字,那么这个函数就不是普通函数,而是一个generator

注:generator和函数执行的流程不一样,

函数是顺序执行,遇到return语句或则最后一行函数函数语句就返回。

而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行从上次返回的yield语句处继续执行

1 defpacket():2 for i in range(1,10):3 print("开始生产包子")4 yield "第 %d 屉包子" %(i)5 print("卖包子,买完再生产")6 cs = packet() #生成一个做包子的生成器,相当于做包子的

7 #print(cs)

8 q = print(cs.__next__()) #卖包子的

9 print(cs.__next__())10 for i incs:11 print(i)

#单线程一边发送,一边执行

2 importtime3 defconsumer(name):4 print("%s 准备吃包子啦!" %name)5 whileTrue:6 baozi = yield

7

8 print("包子[%s]来了,被[%s]吃了!" %(baozi,name))9 defproducer(name):10 c = consumer('A')11 c2 = consumer('B')12 c.__next__()13 c2.__next__()14 print("老子开始准备做包子啦!")15 for i in range(10):16 time.sleep(1)17 print("做了2个包子!")18 c.send(i) #发送的值,就是yield的返回值

19c2.send(i)20 producer("xixi")

1.2.3生成器函数总结

1.生成器函数语法上和普通函数类似:生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值

2.生成器自动实现迭代器协议,迭代完,就不能再次迭代。

3.状态挂起:生成器使用yield语句返回一个值。挂起该生成器函数的状态。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值