zoukankan      html  css  js  c++  java
  • 函数4—迭代器与生成器

    基础概念
    迭代器:

    为什么: 提供了一种不依赖于索引的取值方式,如字典,集合,文件等没有索引的类型需要循环取出元素
    迭代器是惰性计算,更节省内存,迭代器在内存中只是一个内存地址,一次只取一个值

    缺点:永远无法获取迭代器的长度,使用不如列表索引取值灵活
    一次性的,只能往后取值
    可迭代的:对象本身有__iter__方法
    i = iter(n) or i = n.__iter__() i 为n的迭代器
    next(i) or i.__next__() 利用迭代器输出内容,一次输出一个


    生成器:
    定义: 函数中包含yield语句
    将生成器函数(有yield)返回的g作为迭代器使用,这个g就是生成器, 每次next生成器,就执行一次函数
    即 将整个函数作为迭代器
    yield与return 的区别:
    return只能执行一次函数就彻底结束,yield 能多次返回值
    yield的作用:
    把函数的返回值变成迭代器 ---------》生成器
    将iter next函数封装到函数内部, 将函数变为一个迭代器对象(将函数变成了一个类似序列类型的对象)
    多次输出函数运行结果
    每次触发就运行一次函数,保存函数在暂停及继续下一次运行时的状态


    协程函数 本质是一种生成器函数,函数中的yield由表达式所写 面向过程编程的主要形式
    e.send() 与 next(e)的区别:
    二者的共同之处是度可以让函数在上次暂停的位置继续运行
    二者都可以返回yield后面的返回值
    如果函数内yield是表达式形式,那么必须先next(e)
    send在触发下一次next的时候会给上次的yield传值
    所有的生成器函数都只能通过next send 和for循环来逐次运行函数,且生成器函数本身不会运行


    迭代器 与生成器的相同:生成器是迭代器的一种,生成器具有迭代器全部的功能 惰性计算
    不同:
    迭代器只是每次返回一个已知序列的值
    生成器保存了一个算法,比迭代器多了一个功能是边运行边计算,返回一个运算过的序列的值


    迭代器---------->生成器---------->生成器的表达式应用:协程函数----------->面向过程的编程:利用了函数式编程的思想

    l = ['a','b','c','d']
    #while循环列表
    i =0
    while i < len(l):
    print(l[i])
    i += 1
    # for 循环列表
    for i in range(len(l)): #使用索引取出元素
    print(l[i])

    for i in l: #使用for自带的迭代器取出元素
    print(i)

    d = {'a':1,'b':2,'c':3}
    #while 循环字典
    g = d.__iter__() #迭代器g
    print(type(g))
    while True:
    try: #捕捉异常
    print(next(g)) #迭代器的方法__next__()
    except StopIteration:
    break

    #for 循环字典

    for i in g: #g已经是一个迭代器,但for循环中的自动转迭代器不会影响遍历字典
    print(i)

    for i in d: #for循环内包含了iter ,next ,和 自动捕捉异常的函数
    print(i)

    #while循环文件
    while True:
    try:
    print(next(f))
    except StopIteration:
    break
    #for循环文件
    with open('a.txt') as f:
    for line in f:
    print(line.strip())

    f = open('a.txt')
    f.__iter__() #文件本身就是一个迭代器
    print(f.__next__())

    s = 'hello'
    l = [1,2,3]
    t = (1,2,3)
    d = {'a':1}
    s = {'a','b'}
    f = open('a.txt')
    # 查看可迭代对象
    from collections import Iterable
    s.__iter__()
    print(isinstance(l,Iterable))
    #查看迭代器对象
    from collections import Iterator
    f.__next__()
    print(isinstance(l,Iterator))



    #生成器
    def test(): #生成器函数
    print('one')
    yield 1
    print('two')
    yield 2
    print('three')
    yield 3
    print('four')
    yield 4
    print('five')
    g = test() #返回一个生成器 同时也是一个迭代器,可以作为迭代器使用

    g.__next__()
    g.__next__()
    g.__next__()
    g.__next__()
    #生成器的应用
    def countdown(n):
    print('start')
    while n > 0:
    yield n
    n -= 1
    print('done')
    g = countdown(5)

    # 生成器中迭代器的应用
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))

    while True:
    try:
    print(next(g))
    except StopIteration:
    break

    for i in g:
    print(i)
    #生成器有个迭代器的属性:惰性计算 如下函数 生成器可以一直运行,而且内存不会卡
    def func():
    n = 0
    while True:
    yield n
    n += 1
    g = func()
    #print(next(f))
    for i in g:
    print(i)


    print(isinstance((x for x in range(10)),Iterable))
    #生成器应用:随时监听文件中的错误日志
    #/usr/bin/env python
    import time
    def tail(file_path):
    with open(file_path) as f:
    f.seek(0,2)
    while True:
    line = f.readline()
    if not line:
    time.sleep(0.5)
    continue
    else:
    #print(line,end='')
    yield line
    def grep(pattern,lines):
    for line in lines:
    if pattern in line:
    yield line
    g1=tail('/tmp/a.txt')
    g2=grep('error',g1)
    for i in g2:
    print(i)

    #生成器的表达式应用:协程函数
    def eater(name):
    print('%s start to eat food'%name)
    food_list=[]
    while True: #必须加while循环,为每次生成器发送的值创造循环条件
    food = yield food_list
    print('%s got %s to start eat'%(name,food))
    food_list.append(food)
    print('done')

    e = eater('gangdan')

    print(next(e))
    print(e.send('baozi')) #生成器在向函数发送参数时,以元组的形式发送,所以发送多个参数时,要加上()表示元组
    print(e.send('miantiao'))
    print(e.send('mifan'))

    #为生成器添加装饰器
    def nextn(func):
    def wrapper(*args,**kwargs):
    res = func(*args,**kwargs)
    next(res)
    return res
    return wrapper
    @nextn
    def eater(name):
    print('%s start to eat food'%name)
    food_list=[]
    while True:
    food = yield food_list
    print('%s got %s to start eat'%(name,food))
    food_list.append(food)
    print('done')

    e = eater('liuliu')
    e.send('baozi')


    #迭代器应用:实现功能 cat a,txt | grep apple
    import time
    def cat():
    while True:
    with open('a.txt') as f:
    lines = f.readline()
    if not lines:
    time.sleep(1)
    continue
    else:
    yield lines

    def grep(pattern,lines):
    for i in lines:
    if pattern in i:
    print(i)
    exit()


    g = cat()
    grep('apple',g)

    #生成器应用: 把下面的函数改成生成器的形式,执行生成器函数得到一个生成器g,然后每次g.send(url),
    # 打印页面内容,利用g可以无限send
    from urllib.request import urlopen
    def opener(url):
    while True:
    print(urlopen(url).read())
    url=yield
    g = opener('http://www.baidu.com')
    next(g)
    g.send('http://www.360.com')


    def get(url):
    while True:
    def index():
    res = urlopen(url).read()
    print(res)
    index()
    url = yield

    g = get('http://www.baidu.com')
    next(g)
    g.send('http://www.360.com')
  • 相关阅读:
    快速排序算法
    HTTP中的重定向和请求转发的区别
    单链表的逆置(头插法和就地逆置)
    水仙花数学习
    构建n位元的格雷码
    算法学习day01 栈和队列
    数据结构学习总结 线性表之双向链表
    设计模式
    Nginx 初步认识
    数据结构学习总结(2) 线性表之单链表
  • 原文地址:https://www.cnblogs.com/liuguniang/p/6714929.html
Copyright © 2011-2022 走看看