面向过程编程-迭代器和生成器

 

一:什么是迭代器?

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_())
    exceptbreak

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解析——》执行功能

    

 

  

 

 

 

 

 





















 

posted @ 2018-04-01 09:56  Ryansuperwa  阅读(213)  评论(1编辑  收藏  举报