首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python基础知识7:生成器和迭代器、递归

1、迭代器:

任何可以用 for in 来迭代读取的都是迭代容器,例如lists、tuples、sets、files、dict、str、生成器等。这些容器中的元素可以逐个地迭代获取。

以下为一个简单的迭代器:

list=[1,2,3,4,5]

foriinlist:

print(i)

执行结果:

2、生成器

生成器与普通函数的区别

生成器是由函数创造的,类似于装饰器,都是在函数上面加上一个东西;而其关键词就是yield,当python看到函数中有yield时,就会将一个普通函数变成一个 generator生成器函数。

生成器(generator)概念:

生成器不会把结果保存在一个系列中,而是保存生成器的状态,在每次进行迭代时返回一个值,直到遇到StopIteration异常结束。

yield 语句的功能:

保存上次执行的位置,下次执行时,直接从这个位置开始,而不是一次生成全部的循环。一个函数或者子程序都只能 return 一次,但是一个生成器能暂停执行并返回一个中间的结果

案例1:正常的普通函数执行

deffunc():#创建普通函数

print("start")

return123

func()#执行函数,打印出来start

执行结果:

案例2:正常的普通函数执行,并调用返回值

deffunc():#创建普通函数

print("start")

return123

ret=func()#执行函数,打印start

print(ret)#将函数值打印出来,打印函数返回值123

执行结果为:

案例3:增加yield,变成生成器。第一次执行yield后会挂起函数。

因此当调用下面的函数时执行结果为空

deffunc():#创建普通函数

print("start")

yield1#第一次执行yield后,会挂起函数

yield2

yield3

return123

func()#执行函数

目前执行结果为空。

可以打印下函数的返回值看下,是一个生成器

deffunc():#创建普通函数

print("start")

yield1#第一次执行yield后,会挂起函数

yield2

yield3

return123

ret=func()#执行函数

print(ret)

执行结果如下,为生成器:

案例4:当执行循环时,才会进函数取值。

当有循环执行时,会在上次的结果的基础上依次往下执行;

deffunc():#创建普通函数

print("start")

yield1#取第一次循环,并且挂起,把值赋给i

yield2

yield4

return123

ret=func()#执行函数

foriinret:

print('i',i)

执行结果:

案例5:调用生成器:可以用next控制,每次执行到yield挂起,只取yield之前的内容

生成器函数在每次暂停执行时,函数体内的所有变量都将被封存(freeze)在生成器中,并将在恢复执行时还原,并且类似于闭包,即使是同一个生成器函数返回的生成器,封存的变量也是互相独立的。

deffunc():#创建普通函数

print("start")

yield1

print("a")

yield2

print("b")

yield4

print("c")

return123

ret=func()#执行函数

r1=ret.__next__()#进入函数找,执行到第一个yield,挂起,仅获取之前的数据

print(r1)

执行结果:

设置了三个yield,可以调用4次。每个yield执行后挂起,只返回yield之前的内容。

在一个生成器中,如果没有return,则默认执行到函数完毕时返回StopIteration。

如果遇到return,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。

deffunc():#创建普通函数

print("start")

yield1#增加yield

print("a")

yield2

print("b")

yield3

print("c")

return123

ret=func()#执行函数

r1=ret.__next__()#进入函数找,执行到第一个yield,挂起,仅获取之前的数据

print(r1)

r2=ret.__next__()#接着上次执行的位置,执行到第二个yield,挂起

print(r2)

r3=ret.__next__()#接着上次执行的位置,执行到第三个yield,挂起

print(r3)

r4=ret.__next__()#进入上次执行的位置,执行print("c")

print(r4)

执行结果:

如果第五次就会出错。

deffunc():#创建普通函数

print("start")

yield1#增加yield

print("a")

yield2

print("b")

yield3

print("c")

return123

ret=func()#执行函数

r1=ret.__next__()#进入函数找,执行到第一个yield,挂起,仅获取之前的数据

print(r1)

r2=ret.__next__()#接着上次执行的位置,执行到第二个yield,挂起

print(r2)

r3=ret.__next__()#接着上次执行的位置,执行到第三个yield,挂起

print(r3)

r4=ret.__next__()#进入上次执行的位置,执行print("c")

print(r4)

r5=ret.__next__()#因为已经无yiled,则报错

print(r5)

执行结果:

案例6:生成器需要用迭代器来取数。如下为先使用next取数案例。

每次都从上次挂起的地方继续执行,一直到下一次的yield。

defmyrange(arg):

start=

while True:

yieldstart

start+=1

ret=myrange(10)

r1=ret.__next__()#进入函数找到yield,执行完挂起

print(r1)

r2=ret.__next__()#上次挂起的地方,继续执行,直到下一个yield后再挂起

print(r2)

执行结果:

案例7:增加控制条件

defmyrange(arg):

start=

while True:

ifstart>arg:

return

yieldstart

start+=1

ret=myrange(3)

r1=ret.__next__()#进入函数找到yield,执行完挂起,把start赋值给r1

print(r1)

r2=ret.__next__()#上次挂起的地方,继续执行,直到下一个yield后再挂起

print(r2)

r3=ret.__next__()#执行第三次循环

print(r3)

r4=ret.__next__()#执行第四次循环

print(r4)

执行结果:

案例8:使用迭代器来代替next取数

defmyrange(arg):

start=

while True:

ifstart>arg:

return

yieldstart

start+=1

ret=myrange(3)

foriteminret:

print(item)

执行结果:

案例9:迭代器取每个元素

#生成器应用案例:

defflatten(nested):

try:

ifisinstance(nested,str):# 如果是字符串,转移到TypeError。

raiseTypeError#引发异常

forsublistinnested:

forelementinflatten(sublist):#把sublist传递给nested,先执行完flatten

print('got:', element)

exceptTypeError:#每次执行flatten时都会执行此函数

yieldnested

L = ['aaadf', [1,2,3],20,40, [55, [66, [88, [99]],'ddf'],7]]

foriinflatten(L):

print(i)

执行结果:

3、递归函数

案例10:递归案例,return的值会依次传递

defd():

return'123'

defc():

r=d()

returnr

defb():

r=c()

returnr

defa():

r=b()

print(r)

a()

执行结果为123

案例11:递归实现阶乘:实现1*2*3*.....7

deffun(num):

ifnum==1:

return1

returnnum*fun(num-1)

x=fun(7)

print(x)

执行结果:5040

http://python.jobbole.com/87805/

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171217G0DOT200?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券