码迷,mamicode.com
首页 > 其他好文 > 详细

十一、迭代器、生成器

时间:2017-11-28 01:43:27      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:管道   函数   并且   方法   __iter__   索引   版本   过滤   put   

迭代

  迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是基于下一次迭代的结果

  如公司软件:基于第一次基础上修改,发第二个版本,基于第二个,发第三个。。。

循环
while True:
    name = input(‘名字:‘)
    print(name)

迭代
count = 0
while count<10:
    print(count)
    count+=1

可迭代对象:

  python提供的不依赖索引的迭代方式,会为一些对象内置 __iter__ 方法

  只要有 __iter__ 方法的对象,就是可迭代对象

  可迭代对象有:

字符串
列表
元组
字典
集合
文件对象

  对象执行 __iter__ 方法后,得到的就是迭代器

迭代器

  既有 __iter__  方法,又有 __next__ 方法

  __next__方法不依赖索引迭代对象,__next__一次迭代一次

  当迭代超出,会提示 StopIteration,没有这个值

d = {‘a‘:1,‘b‘:2,‘c‘:3,‘d‘:4}
i = d.__iter__()                       # 得到迭代器  i
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())        # StopIteration

  优点:

        1.不依赖索引(统一了迭代方式)

      2.节省内存,惰性计算,同一时间内存只有一个值 (比如读文件内容,不一下全读出来,节省内存) 

  缺点:

      1.只能一次性往后next取值

      2.无法获取长度

 

for循环与迭代器:

  之前说过字典没有索引,直接通过 for  i  in dict 可以取值

  原理就是:

i = d.__iter__()
i.__next()

被循环的对象执行__iter__方法到的 i
i 自动执行__next__
直到报出StopIteration结束,for循环捕捉处理

  所以 for 可以直接循环迭代器:

def func():
    print(1)
    yield  1
    print(2)
    yield   None
    print(3)
    yield         #这里不加yield,报StopIteration
g = func().__iter__()
for i in g:
    print(i)            #  1  None  None  

  


 

生成器 

  生成器函数

 

    函数体包含 yield 关键字,这个函数执行的结果就是生成器

    yeild 将函数做成了生成器,遵循迭代器的取值方式

def func():
    print(‘真‘)
    yield
    print(‘帅‘)
g = func()
print(g)             # <generator object func at 0x00000214686B6990>

  生成器也具有 __iter__ 和 __next__ 方法,实际生成器就是迭代器:

l = [1,2,3,4,5]
b = l.__iter__()
print(b.__next__())         #  触发一次迭代列表操作,取一次值就结束

def func():
    print(‘真‘)
    yield
    print(‘帅‘)
g = func()
g.__next__()            # 触发一次函数的执行,函数的结束标准是 return 这里的 yield 就相当于 return 的终止执行操作


def func():
    print(1)
    yield  1
    print(2)
    yield   None
    print(3)
    yield         #这里不加yield,报StopIteration
g = func()
g.__next__()
g.__next__()
g.__next__()
# 碰到yield 就暂停,返回值,然后再执行next,函数继续从暂停位置执行,依次类推;
# 如果函数执行最后没有返回值,就报StopIteration
# 与 return 的区别:     1.可以返回多次值,return只能1次
#                       2.保存执行状态,继续向下执行,return执行就终止函数

 

模拟linux中 tail -f 命令(动态查看文件新增的一行内容):

  分析:

    1.一次读一行:readline

    2.最新一行:光标要在每行的最后位置

    3.循环上两步操作

    4.读到内容返回,没读到重新进入循环

import time
def tail(filepath,encoding=‘utf-8‘):
    with open(filepath,encoding=encoding) as f:
        f.seek(0,2)
        while True:
            line = f.readline()
            if line:
                print(line,end=‘‘)
            else:
                time.sleep(1)
tail(‘a.txt‘)

    增加过滤 tail - f a.txt | grep ‘shuai‘  过滤出 shuai

import time
def tail(filepath,encoding=‘utf-8‘):
    with open(filepath,encoding=encoding) as f:
        f.seek(0,2)
        while True:
            line = f.readline()
            if line:
                yield line
            else:
                time.sleep(1)
# g = tail(‘a.txt‘)

def grep(lines,item):
    for line in lines:
        if item in line:
            yield line
grep_g = (tail(‘a.txt‘),‘shuai‘)
for i in grep_g:
  print(i)

  |  管道符:左边的执行结果返回给右边

再来个

def foo(n):
    while n>0:
        yield n
        n-=1
g = foo(6)
print(g.__next__())     # 6
print(g.__next__())     # 5
for i in g:
    print(i)            # 4 3 2 1

迭代器是一次性的,只能一直往后取,for把剩下的值取了


def foo(n):
    while n>0:
        yield n
        n-=1
g = foo(6)
for i in foo(6):
    print(i)        # 6 5 4 3 2 1
for i in foo(6):
    print(i)        # 6 5 4 3 2 1 


这里的两个for 是循环单独的生成器


def foo(n):
    while n>0:
        yield n
        n-=1
print(foo(6).__next__())        # 6
print(foo(6).__next__())        # 6

这两次也是操作了两个生成器

  

 

十一、迭代器、生成器

标签:管道   函数   并且   方法   __iter__   索引   版本   过滤   put   

原文地址:http://www.cnblogs.com/Mr-chenshuai/p/7906519.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!