首页 > 代码库 > 计算机基础-----迭代器 和生成器

计算机基础-----迭代器 和生成器

迭代器

1.1迭代器 和 可迭代对象

迭代器的本质   就是for循环调用的底层内置函数的运用

可迭代对象:字符串、列表、元组、字典、集合都是可迭代的对象 

迭代器协议--必须要满足两点才可以叫做可迭代协议

:  内部实现了__iter__和__next__

1.2迭代器----iterator

通过代码来理解

技术分享
‘‘‘
dir([1,2].__iter__())是列表迭代器中实现的所有方法,dir([1,2])是列表中实现的所有方法,都是以列表的形式返回给我们的,为了看的更清楚,我们分别把他们转换成集合,
然后取差集。
‘‘‘
#print(dir([1,2].__iter__()))
#print(dir([1,2]))
print(set(dir([1,2].__iter__()))-set(dir([1,2])))

结果:
{__length_hint__, __next__, __setstate__}
View Code

迭代器中的三个方法的作用

技术分享
iter_l = [1,2,3,4,5,6].__iter__()
#获取迭代器中元素的长度
print(iter_l.__length_hint__())
#根据索引值指定从哪里开始迭代
print(*,iter_l.__setstate__(4))
#一个一个的取值
print(**,iter_l.__next__())
print(***,iter_l.__next__())
View Code

在for循环中,就是在内部调用了__next__方法才能取到一个一个的值,,但是取不到值的时候会报错

技术分享
经典  一眼就能看出来
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)
View Code

内置函数:next和iter方法

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

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

range函数的返回值是一个可迭代对象
View Code

生成器--没有迭代协议但是还想要迭代 

                                 --   自己生一个

2.1python自带的生成器

  

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

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

1.3 生成器Generator的本质:开发者自定义的生成器   ..惰性运算 ...节省内存..

1.4生成器函数: 一个包含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))

初识生成器函数
View Code

代码体现生成器不占内存

技术分享
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))

初识生成器函数
View Code

监控文件这点自己不是太懂记得问一下

技术分享
import time


def tail(filename):
    f = open(filename)
    f.seek(0, 2) #从文件末尾算起
    while True:
        line = f.readline()  # 读取文件中新的文本行
        if not line:
            time.sleep(0.1)
            continue
        yield line

tail_g = tail(tmp)
for line in tail_g:
    print(line)

生成器监听文件输入的例子
View Code

 

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

#老男孩由于峰哥的强势加盟很快走上了上市之路,alex思来想去决定下几个鸡蛋来报答峰哥

egg_list=[鸡蛋%s %i for i in range(10)] #列表解析

#峰哥瞅着alex下的一筐鸡蛋,捂住了鼻子,说了句:哥,你还是给我只母鸡吧,我自己回家下

laomuji=(鸡蛋%s %i for i in range(10))#生成器表达式
print(laomuji)
print(next(laomuji)) #next本质就是调用__next__
print(laomuji.__next__())
print(next(laomuji))

峰哥与alex的故事

(老师总结的很好  我能看懂  )

#列表解析
sum([i for i in range(100000000)])#内存占用大,机器容易卡死
 
#生成器表达式
sum(i for i in range(100000000))#几乎不占内存

 

 

总结:

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

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

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

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

而不用多此一举的先构造一个列表:

sum([x ** 2 for x in xrange(4)]) 

 

 

 

 

 

 

 

 

             

 

计算机基础-----迭代器 和生成器