python之路——函数迭代,生成器

---恢复内容开始---

迭代器 生成器

迭代器:

1, 什么是迭代器协议

 ① dir(被测对象) 如果它含有 __iter__,那这个对象叫做可迭代对象,遵循可迭代协议。

 ②  可迭代对象:iterable 可以转换 迭代器(如何实现:都像内部定义一个 __iter__()方法)

  迭代器(iterator)遵循迭代器协议

2, 迭代器

1,只含有__iter__方法的数据是课迭代的对象

l = [1,2,3,4]
print('__iter__' in dir(l))

 

2,含有__iter__方法,并且含有__next__方法的数据是迭代器。

print(dir([1,2].__iter__()))

 

3, 迭代器的意义:

① 迭代器节省内存

② 迭代器有惰性机制

③ 迭代器不能反复,一直向下执行。

4, for 循环机制

for 可以循环有: 字符串,列表,元祖,字典,集合,说明它们都是可以被迭代的。

在for循环中,就是在内部调用了__next__方法才能取到一个一个的值。

那接下来我们就用迭代器的next方法来写一个不依赖for的遍历。

l = [1,2,3,4]
l_iter = l.__iter__()
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)

这是一段会报错的代码,如果我们一直取next取到迭代器里已经没有元素了,就会抛出一个异常StopIteration,告诉我们,列表中已经没有有效的元素了。

 

这个时候,我们就要使用异常处理机制来把这个异常处理掉

l = [1,2,3,4]
l_iter = l.__iter__()
while True:
    try:
        item = l_iter.__next__()
        print(item)
    except StopIteration:
        break

那现在我们就使用while循环实现了原本for循环做的事情,我们是从谁那儿获取一个一个的值呀?是不是就是l_iter?好了,这个l_iter就是一个迭代器。

1,内部含有__iter__方法,他会将可迭代对象先转化成迭代器,然后在调用__next__方法。

2,它有异常处理方法 

range 它是可迭代对象,不是迭代器

验证range 是不是迭代器

print('__next__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__
print('__iter__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__

from collections import Iterable from collections import Iterator
print(isinstance(range(100000000),Iterable))
print(isinstance(range(100000000),Iterator)) #验证range执行之后得到的结果不是一个迭代器

生成器:

1, 生成器的本质就是迭代器,迭代器,生成器是python自己用python代码写的迭代器

2,生成器的特点:

①可以用生成器函数写

 

②可以用各种推导式构建迭代器

   

③可以通过数据转化

3,return 和 yield 的区别

 ①  return 返回给调用者值,并结束此函数

 ②  yiled  返回给调用者值,并将指针停留在当前位置

import time
def genrator_fun1():
    a = 1
    print('现在定义了a变量')
    yield a
    b = 2
    print('现在又定义了b变量')
    yield b

g1 = genrator_fun1()
print('g1 : ',g1)       #打印g1可以发现g1就是一个生成器
print('-'*20)   #我是华丽的分割线
print(next(g1))
time.sleep(1)   #sleep一秒看清执行过程
print(next(g1))

 

 4, send :

1,给上一个 yiled 整体发送一个值

2, send 不能给最后一个 yiled 发送值

3, 获取第一个值的时候,不能用 send 只能用 next

def generator():
    print(123)
    content = yield 1
    print('=======',content)
    print(456)
    yield2

g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello')   #send的效果和next一样
print('***',ret)

 

 

---恢复内容结束---

posted @ 2018-02-06 20:49  lzg世界  阅读(110)  评论(0编辑  收藏  举报
Live2D