day 13 迭代器 和 生成器

一。迭代器

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

for example:

from collections import Iterable

li = [2,3,4,6]

print(isinstance(li,Iterable))

2.思考:for是如何进行迭代的
print(dir(可迭代对象))
如果可迭代对象中有iter方法,就是可迭代的
print(li.__iter__())

3.迭代器(iterator)
迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
for循环,能便利一个可迭代对象

4.将可迭代对象转化为迭代器(可迭代对象。__iter__())
内部使用__next__方法,一个一个取值。
加了异常处理功能,取值到底后自动停止

用while循环模拟for循环:
li = [1,3,4,6]
li_iter = li.__iter__()
while True:
try:
item = li_iter.__next__()
print(item)
except Exception:
break

5.思考?有了for循环,为什么还要用迭代器
for循环可以便利有序的可迭代对象,但是不可以便利无序的可迭代对象
所以我们要使用 可迭代器(iterator)

如此,这就是无所不能的for循环,最重要的一点,转化成迭代器,在循环时,同一时刻在内存中只出现一条数据,极大限度的节省了内存~(最主要因素)


二。生成器
有哪些可迭代的内部生成器(map,filter,enumerate,zip)

.1初始生成器

我们知道的迭代器有两种:一种是调用方法(系统内置迭代器和迭代对象)直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。

 

Python中提供的生成器:

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行

生成器Generator:

  本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)

  特点:惰性运算,开发者自定义

 

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

def generate():
    print(666)
    print(222)
    content = yield 1
    print(content)
    print(000)
    yield 2
g = generate()
g.__next__()
g.send('hello')
#g.__next__()

 


2.2 生成器函数


一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。


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))

初识生成器函数
forexample


假如我想让工厂给学生做校服,生产2000000件衣服,我和工厂一说,工厂应该是先答应下来,然后再去生产,我可以一件一件的要,也可以根据学生一批一批的找工厂拿。
而不能是一说要生产2000000件衣服,工厂就先去做生产2000000件衣服,等回来做好了,学生都毕业了。。。

复制代码
def produce():
    """生产衣服"""
    for i in range(2000000):
        yield "生产了第%s件衣服"%i

product_g = produce()
print(product_g.__next__()) #要一件衣服
print(product_g.__next__()) #再要一件衣服
print(product_g.__next__()) #再要一件衣服
num = 0
for i in product_g:         #要一批衣服,比如5件
    print(i)
    num +=1
    if num == 5:
        break




send()方法:
#send 获取下一个值的效果和next基本一致
#只是在获取下一个值的时候,给上一yield的位置传递一个数据
#使用send的注意事项
    # 第一次使用生成器的时候 是用next获取下一个值
    # 最后一个yield不能接受外部的值

复制代码
三,列表推导式和生成器表达式  

三,列表推导式和生成器表达式

l = [i for i in range(10)]
print(l)
l1 = ['选项%s'%i for i in range(10)]
print(l1)

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

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

3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:

sum(x ** 2 for x in range(4))

































 
posted @ 2018-04-03 21:44  Coca-Mirinda  阅读(123)  评论(0)    收藏  举报