zoukankan      html  css  js  c++  java
  • 迭代器和生成器函数

    引入:

    l = [1,2,3,4,5]
    s = {1,2,3,4}
    for i in l:
        print(i)

    如果代码是:

    for i in 50:
        print(i)

    这个运行不了。输出结果是 'int' object is not iterable

    iterable是可迭代的意思。

    哪些可以迭代呢?这些可以str、list、tuple、set、dic等

    可迭代的标志是  _iter_。

    那我们如何判断是否可以迭代呢?

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

    双下划线的内置方法一般不用这种方法调用:

    print(next(l.__iter__()))

    而是用这种方法调用:

    print(next(iter(l)) )

    小结:

    (1)可迭代协议——凡是可迭代的内部都有一个__iter__方法

    (2)迭代器里既有iter方法,又有next方法 ——迭代器协议

    (3)通过iter(o)得到的结果就是一个迭代器

    (4)0是可迭代的对象

    判断是否是迭代器和可迭代对象的方法:

    from collections import Iterable
    from collections import Iterator
    s = 'abc'
    print(isinstance(s,Iterable))
    print(isinstance(s,Iterator))
    print(isinstance(iter(s),Iterator))

    生成器包括两个方面:生成器函数和生成器表达式

    生成器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。

    如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。

    python中内置的生产器:

    (1)生成器函数:关键字是yield,yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次继续运行。

    (2)生成器表达式:类似于列表推导式,但是返回的是一个对象而不是一个结果列表 ,即惰性运算。

    生成器函数:一个含有yield的函数就是生产器函数。通过调用返回的是一个对象,而不是结果列表。通过每一次对这个对象的请求就得到一个值def func():    print('aaaa')

        a=1
        yield a#返回第一个值
        print('bbbbb')
        yield 12#返回第二个值
        print('cccccc')
        yield 56#返回第三个值
    ret=func()#拿到一个生成器
    print(next(ret))#取第一个值
    print(next(ret))#ret不可以用func替代
    print(next(ret))

    生成器例子:可以监听一个文本输入的文本

    import time
    def tail(filename):
        with open(filename) as f:
            f.seek(0,2)
            while True:
                line=f.readline()
                if not line:
                    #time.sleep()
                    continue
                yield line
    for line in tail('监视文件'):
        print(line,end='')

    可以计算移动平均值的例子:

    def averager():
        total=0
        day=0
        average=0
        while True:
            day_num=yield average
            total+=day_num
            day+=1
            average=total/day
    avg=averager()#直接返回生成器
    next(avg)#激活生成器avg.sed(),什么都 不send和next效果一样
    print(avg.send(10))
    print(avg.send(15))
    print(avg.send(80))

    装饰器版计算移动平均值的例子:

    def wrapper(func):
        def inner(*arge,**kwargs):
            ret=func(*arge,**kwargs)
            next(ret)
            return ret
        return inner
    @wrapper
    def averager():
        total=0
        day=0
        average=0
        while True:
            day_num=yield average
            total+=day_num
            day+=1
            average=total/day
    avg=averager()#直接返回生成器
    # next(avg)#激活生成器avg.sed(),什么都 不send和next效果一样
    print(avg.send(10))
    print(avg.send(15))
    print(avg.send(80))

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

    列表推导式:(两个代码实现相同的效果)

    for i in range(100):
        print(i*i)
    l=[i*i for i in range(100)]
    print(l)
    l = [{'name':'v','age':28},{'name':'v'}]
    name_list = [dic['name'] for dic in l]
    print(name_list)

    生成器表达式:

    l=(i*i for i in range(100))
    print(next(l))
    print(next(l))
    print(next(l))
    print(next(l))
    l = [{'name':'v1','age':28},{'name':'v2'}]
    name_list_generator = (dic['name'] for dic in l)
    #print(name_list_generator)
    print(next(name_list_generator))
    print(next(name_list_generator))

    我们会发现列表推导式和生成器表达式除了括号不一样外都一样。列表推导式是中括号,生成器表达式是小括号。

    区别:列表推导式是把所有的数据都一起算出来,而生成器表达式是一种惰性运算你请求一次给你一个数据。因此相比较来说生成器表达式更节省内存。

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

    print(sum(x**2 for x in range(3)))

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

    print(sum([x**2 for x in range(3)]))

    总结:

    可迭代对象:

     拥有_inter_方法

     惰性计算

    像str、list、tuple、set、dic等

    迭代器:

    拥有_inter_方法和next方法

    像:iter(range()),iter(str),iter(list),iter(tuple),iter(dict),iter(set),reversed(list_o),map(func,list_o),filter(func,list_o),file_o

    特点: 可以用for循环、 可以节省内存、只能用一次

    生成器:本质是迭代器(同时拥有_inter_和next方法)

    是开发人员自己定义的迭代器

    优点:

    1.延迟计算,你请求一次他给你返回一个结果。他不会给你返回所有的结果,不会大量占据内存

    2.代码简洁,容易读

  • 相关阅读:
    Winform 积累
    mvc部署iis遇到的问题总结
    开始我的BLOG生活
    sql 总结
    ajax:AutoCompleteExtender版本问题
    ancms即将上线
    ancms v2.3语言介绍
    asp.net的cms 核心代码篇
    div+css布局
    js词法结构
  • 原文地址:https://www.cnblogs.com/1a2a/p/7275501.html
Copyright © 2011-2022 走看看