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

迭代器和生成器

时间:2017-08-06 16:05:19      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:return   ==   readline   开发者   协议   family   print   bsp   自己   

 

 

 

迭代器和生成器

1、什么是迭代器和可迭代对象

(1) 可迭代对象

定义:内部实现了__iter__方法,即可迭代协议。可迭代协议的定义非常简单,可以被迭代要满足的要求就叫做可迭代协议。

(2)迭代器

定义:代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。

补充:迭代器是python内置的,如果一个对象是可迭代的但不一定是迭代器。

迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行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
可迭代对象与迭代器

2、初识生成器

定义:我们自己写的这个能实现迭代器功能的东西就叫生成器。

(1)python中提供的生成器

1、生成器函数

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

2、生成器表达式

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

(2)生成器generator

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

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

3、生成器函数

(1)定义:一个包含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))
生成器函数

(2)生成器的应用
1、监听文件

技术分享
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
监听文件

2、计算移动平均值

技术分享
def init(func):  #在调用被装饰生成器函数的时候首先用next激活生成器
    def inner(*args,**kwargs):
        g = func(*args,**kwargs)
        next(g)
        return g
    return inner

@init
def averager():
    total = 0.0
    count = 0
    average = None
    while True:
        term = yield average
        total += term
        count += 1
        average = total/count


g_avg = averager()
# next(g_avg)   在装饰器中执行了next方法
print(g_avg.send(10))
print(g_avg.send(30))
print(g_avg.send(5))
计算移动平均值

3、yield from的应用

技术分享
def gen1():
    for c in AB:
        yield c
    for i in range(3):
        yield i

print(list(gen1()))

def gen2():
    yield from AB
    yield from range(3)

print(list(gen2()))
yield from 的应用

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

列表推导式

技术分享
print([i for i in range(10) if i%2==1])
列表推导式

生成器表达式

 

技术分享
print((i for i in range(10) if i%2==1))
生成器表达式

总结:1、列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存。
           2、列表解析式返回的是一个结果,而生成器表达式返回的是一个生成器。

使用生成器的优点:

1.延迟计算,一次返回一个结果

2.、提高代码可读性

 

 

 

 

 

 

 

 

 

 

迭代器和生成器

标签:return   ==   readline   开发者   协议   family   print   bsp   自己   

原文地址:http://www.cnblogs.com/hzauq/p/7294742.html

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