面向过程编程-迭代器和生成器
一:什么是迭代器?
1.什么是迭代
迭代是一个重复的过程,并且每次重复都是基于上一次的结果而来的
while True: print(‘------》’)
没有基于上一次的结果,while这里仅仅是循环
l=['a','b','c'] n=0 while n<len(l): print(l[n]) n+=1
每一次的n都是基于上一次n,这里是迭代
二:什么是迭代器
要想了解迭代器到底是什么?必须了解一个概念,即什么是可迭代对象。
可迭代对象,在python中,但凡内置有_iter_方法的对象,都是可迭代对象。
#以下都是可迭代的对象 strl='hello' listl=[1,2,3] tupl=(1,2,3) dic={'x':1} sl={'a','b','c'} f=open('a.txt','w',encoding='utf-8')
除了数字类型
三:迭代器
1.什么是迭代器和举例
迭代取值的工具,可迭代对象执行_iter_方法得到的返回值就是迭代器对象。
以上都是可迭代的对象,我们以前学习的都是可以迭代,但是受限于必须有索引。
而迭代器对象可以避免引用索引,避开这个短处。
字典:
dic={'x':1,'y':2,'z':3}
iter_dic=dic._iter_()
print(tier_dic._next_())
print(tier_dic._next_())
电脑输出:
x
y
z
集合:
sl={'a','b','c'} iter_sl=sl._iter_() print(iter_sl._next_()) print(iter_sl._next_()) print(iter_sl._next_()) print(iter_sl._next_()) print(iter_sl._next_()) 电脑输出: b a c print(iter_sl._next_()) stopiteration
列表:
list=[1,2,3] iter_list=list_iter_() print(iter_list.-next-()) print(iter_list._next_()) print(iter_list._next_())
电脑输出:
1
2
3
字符串:
l=‘hello’ iter_l=l._iter_() while True: print(iter_l._next_())
电脑输出:
h
e
l
l
o
但执行的时候会报错
增加抛出异常机制:
l=[1,2,3,4,5]
iter_l=l._iter_()
while True:
try:
print(tier_l._next_())
except StopIteration:
break
文件:
l=open('a.txt','r',encoding='utf-8')iter_l=l._iter_()
iter_l=l._iter_()
while True:
try:
print(iter_l._next_())
except StopIteration:
break
电脑输出:
11111111
222222
333333
444444
注意:
‘\n’打印出来了空行
2.for循环称之为迭代器循环,in后必须是可迭代对象或者迭代器,因为for要调用系统内置的_iter_方法
l=open ('a.txt','r',encoding='utf-8')
for line in l :
print(line)
for调用了系统内置方法_iter_
3.迭代器的优点:
1.提供了一种可以不依赖索引的取值方法
2.只生成一个迭代器对象,更加节省内存
l=open('a.txt','r',encoding='utf-8')
for line in l:
print(line)
电脑输出:
只是一个内存空间地址而已
4.迭代器的缺点:
1.取之麻烦,只能一个一个的next取出来
2.取值方向只能往后取,而且是一次性使用,无法复用
x=[1,2,3]
iter_x=x._iter_()
while True:
try:
print(tier_x._next_())
except:
break
print('第二次====================》‘)
iter_x=x._iter_(). (必须新建才能复用)
while True:
try:
print(iter_x._next_())
except:
break
5.可迭代的对象Vs迭代器对象
可迭代对象(list,str,tuple,dict,set,file)
1.获取可迭代对象的方式:无需获取,python内置str,list,dict,set,file都是可迭代对象
2.特点:
内置_iter_方法的都可以叫做可迭代对象,执行该方法会拿到一个迭代器对象
迭代对象:
1.获取迭代器对象的方式,执行可迭代对象的_iter_方法,拿到的返回值就是迭代器对象
2.内置有_next_方法,执行该方法会拿到迭代器对象的一个值(value)
3.内置有_iter_方法,执行该方法会拿到迭代器本身(内存地址)
》》》文件有时候本身较大,占用太多内存,必须定义为一个迭代器对象,节省内存
四、生成器yield基础
1.生成器本质就一个迭代器,相当于自己造了一个母鸡。
生成器的用法其实就是迭代器的用法:
yield的用法其实就是迭代器的用法:
yield的用法(针对任何可迭代对象):
函数内包含yield关键字,在调用函数,就不会执行函数体代码,
拿到返回值就是一个生成器对象
def chicken (): print('----->first') yield 1 print('------>second') yield 2 print('------->third') yield 3 obj=chicken() print(obj)
电脑输出:(输出的是内存地址)
<generator object chicken at 0x1031ed150>
def chicken (): print('----->first') yield 1 print('------>second') yield 2 print('------->third') yield 3 obj=chicken() res=obj.__next__() print(res) res1=obj.__next__() print(res1) res2=obj.__next__() print(res2)
电脑输出:
----->first 1 ------>second 2 ------->third 3
2.yield的过程:
1、iter_obj=obj._iter_(),拿到迭代器
2、出发iter_obj._next_(),拿到该方式的返回值,赋值给item
3、周而复始,直到函数内不再有yield,即取之完毕
4、for会检测到StopIteration异常,结束循环
for item in obj:
print(item)
3、yield的功能
a》与return类似,都可以返回值,不一样在于,yield可以返回多个值而且可暂停,
再次执行可继续下一步操作,return到了就停止不在继续执行。
b》为封装好的函数能够使用_iter_和_next_的方法。
c》遵循迭代器的取值方式._next_(),触发函数的执行和函数的保存方式都是通过yield保存起来的。
def foo(): print('starting') while True: x=yield print('value: ',x) g=foo() next(g) # (next(g)==g.send(None)) g.send(2) # send的效果:1、将携带的值传给yield,注意的是yield,而不是x,然后yield赋值给x 2、send()方法和next()方法 # 一样的功能,也就是继续执行,直到碰到yield结束
yield表达形式(例如:x=yield)下,生成器会有一个send的操作:
send的效果:
1.先从一个暂停位置的那个yield传一个值,然后yield会把值赋值x
2.与next的功能一样
3.send传多个值,必须以元组的形式
def good(func): def good1(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return good1 @good def eater(name): print('%s starting to eat'%name) food_list=[] while True: food=yield food_list food_list.append(food) print('% start to eat %'%(name,food)) m=eater('jason') m.send('火腿')
注意点:
既然send()方法有和next一样的作用,那么我们可不可以这样做:
def foo(): while True: x=yield 函数yield,函数执行的结果就是生成器,即foo()就是生成器。而要执行的话就需要next(g) print('value',x) g=foo() g.send(1) 执行给yield传值,这样行不行呢?
很显然,是不行的:
TypeError: can't send non-None value to a just-started generator
错误提示:不能传递给一个非空值给一个未启动的生成器。
也就是说,在一个生成器函数未启动之前,是不能传递给数值进去的。必须先传递一个None进去
或者调用一次next(),才可以进行传值操作。
4.yield的总结:
a.为我们提供了一种自定义迭代器的方式,可以再函数内调用yield关键词,调用函数拿到的
生成器,生成器就是迭代器。
b.yield可以像是return一样用于返回值
c.yield可以保存函数的执行状态
五、生成器yield的表达形式
def eat(name): print('%s ready to eat' %name) while True: food=yield print('%s start to eat %s' %(name,food)) dog1=eat('alex') dog1._next_() dog1._next_()
dog1.send('骨头')
电脑输出:
alex ready to eat
alex start to eat None
alex start to eat 骨头
六:面向过程编程
1.什么是面向过程
“过程”是其核心,是解决问题的过程,即先做什么,在做什么。
2.基于面向过程编程程序,就好比设计一种流水线,类似机械思维方式
3.总结优缺点:
优点:复杂的问题流程化,进而简单化
缺点:可扩展性差,修改流水线的任意一个阶段都会牵一发而动全身。
应用:扩展性要求不高的场景,典型案例如linux内核,git,http
4.实例:
流水线1:
用户输入用户名、密码——》用户验证——》欢迎界面
流线线2:
用户输入sql——》sql解析——》执行功能