生成器

定义:函数内含有yield关键字的函数运行结果就是生成器,生成器本质上就是迭代器

   生成器本身不可以运行,要运行必须通过next()触发运行,for循环中带有next,while循环也要加了next()才能迭代

   迭代器就是为了好多没有索引的可迭代对象搞出来的,也只有通过next()才能读出来,结合上边那句话理解

1、重点

  生成器,要生成,首先想到return

  生成器是迭代器,是可迭代对象,是生成器

  迭代器是迭代器,是可迭代对象

  可迭代对象指示可迭代对象

2、生成器与return有何区别?

  生成器就是一个函数的内存地址,这个函数内包含有yield这个关键字

  return只能返回一次函数就彻底结束了,而yield能返回多次返回值

  yield和return一样能返回任意值,多个值也是以元组返回

  再循环中的yield是第一次的终点,以后每次的起点和终点,

3、yield干了哪些事?

  yield把函数变成(生成器,生成器就是)迭代器相当于yield把iter()和next()封装到函数内部

  用return返回只能返回一次,而yield返回多次

  函数在暂停以及继续下一次运行时的状态由yield保存

  yield有两种形式,一种是语句形式(生成器函数)就是和return差不多的,另一个是表达式形式(协程函数其实也是生成器原理)

4、生成器理解示例

def test():
    print("first")
    yield 1#return 1
    yield 2
    yield 3
g=test()#g是生成器,是可迭代对象是迭代器
print(g)
next(g)
next(g)#next超出范围还是会报错
print(next(g))#next可以触发迭代器往下走
#运行原理如下:
#print(next(g))
#print(next(test())
#运行test()先print("first")然后碰到yield返回1
#然后结束运行

#用for循环输出g
for i in g:#
    print(i)

def countdown(n):
    print("start")
    while n>0 :
        yield n
        n-=1
    print("done")
g=countdown(5)#g是生成器,是可迭代对象是迭代器
#用next一步一步输出g
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))#超出范围,打印done后报错StopIteration
# 用for循环g
for i in g:
    print(i)
#用while循环输出g
while True:
    try:
        print(next(g))
    except StopIteration:
        break
#因为迭代器是一次性的,所以上边三种循环输出方式只能同时用一种

5、利用生成器的特点实现tail -f /tmp/a.txt |grep 'error'的功能

#/usr/bin/env python
#定义阶段:定义两个生成器函数
import time
def tail(file_path):
    with open(file_path,encoding="utf8") as f:
        f.seek(0,2)
        while True:
            line=f.readline()
            if not line:
                time.sleep(0.5)
                continue
            else:
                yield line
def grep(pattern,target):
    for line in target:
        if pattern in line:
            yield line
#调用阶段:得到两个生成器对象
g1=tail("/tmp/a.txt")
g2=grep("error",g1)
#next触发执行改g2生成器函数 ,用for循环或者while循环来
for i in g2:
    print(i)

6.关于生成器的一道经典面试题

def add(s, x):
    return s + x
def generator():
    for i in range(4):
        yield i
base = generator()
for n in [1, 11]:
    base = (add(i, n) for i in base)
print(list(base))

'''
生成器表达式在没有被next的时候它只是一个表达式,只是一个表达式,不是具体的值
当for n in [1, 11]运行完后,n的值就为11了,这个题可以写成以下这种
'''

def add(s, x):
    return s + x
def generator():
    for i in range(4):
        yield i
base = generator()
n=1
base = (add(i, n) for i in base)
n=11
base = (add(i, n) for i in base)
print(list(base))

  

 

posted @ 2017-04-11 18:50  黄土地上的黑石头  阅读(219)  评论(0编辑  收藏  举报