day14生成器

生成器

我自己想写个可迭代的,——生成器
生成器的本质就是迭代器
因此生成器的所有好处都和迭代器一样
但是生成器是我们自己写的python代码
生成器的实现有两种方式:
1.生成器函数
2.生成器表达式

复制代码
def func():
    return ['衣服1','衣服2000000']

ret = func()
print(ret)

def g_func():
    yield 1

g = g_func()
print(g)  # <generator object g_func at 0x00000000006AAFC0>
generator 生成器  ---> 迭代器
print('__iter__' in dir(g))  # True
print('__next__' in dir(g))  # True
print(g.__next__())  # 1
复制代码

生成器函数和普通函数之间的区别
生成器函数中含有yield关键字
生成器函数调用的时候不会立即执行,而是返回一个生成器

复制代码
def g_func():
    print('aaaa')
    yield 1
    print('bbbb')
    yield 2

g = g_func()
for i in g:
    print(i)
# print(g.__next__())
# print(g.__next__())

def cloth():
    for i in range(1000000):
        yield '衣服%s'%i

g_cloth = cloth()
print(g_cloth.__next__())
print(g_cloth.__next__())
复制代码

 监听文件末尾追加的例子

复制代码
def tail():
    f = open('文件',encoding='utf-8')
  # print('__iter__' in dir(f))  # True
  # print('__next__' in dir(f))  # True
    f.seek(0,2)
    while True:
        line = f.readline()
        if line:
            yield line
        import time
        time.sleep(0.1)
g = tail()
for i in g:
    print(i)
复制代码

send的用法

复制代码
def func():
    print('*'*10)
    a = yield 5
    print('a :',a)
    yield 10

g = func()
num = g.__next__()
print(num)
num2 = g.send('alex')  # 相当于next,但是会传值给yield前的变量
print(num2)
复制代码

send:从哪一个yield开始接着执行,就把一个值传给了哪个yield
send不能用在第一个触发生成器
生成器函数中有多少个yield就必须有多少个next+send

计算移动平均值

复制代码
def init(func):  # 生成器的预激装饰器
    def inner(*args,**kwargs):
        g = func(*args,**kwargs)
        g.__next__()
        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)  # g_avg.__next__()
print(g_avg.send(10))
print(g_avg.send(30))
print(g_avg.send(5))
复制代码

yield from

复制代码
def func():
    a = 'AB'
    b = 'CD'
    yield from a  # 接收一个可迭代对象,相当于下面的for,python3特有
    # for i in a:
    #     yield i
    yield from b
    # for j in b:
    #     yield j
g = func()
for i in g:
    print(i)
复制代码

生成器函数:生成一个生成器的函数
生成器的本质才是迭代器
生成器函数的特点:
带有yield关键字,且调用之后,函数内的代码不执行
触发执行的方式:
next
send send(None) == __next__()
for循环

生成器表达式

复制代码
y = [1,2,3,4,5,6,7,8]
g = (i**2 for i in y )
print(g)  # <generator object <genexpr> at 0x00000000006AAFC0>
print(list(g))  # [1, 4, 9, 16, 25, 36, 49, 64]
# for i in g:
#     print(i)

l = ['鸡蛋%s'%i for i in range(10)]
print(l)
laomuji = ('鸡蛋%s'%i for i in range(10))
for egg in laomuji:
    print(egg)
复制代码

面试题

复制代码
def demo():
    for i in range(4):
        yield i

g=demo()

g1=(i for i in g)
g2=(i for i in g1)

print(list(g1))  # [0, 1, 2, 3]
print(list(g2))  # []
复制代码

 

复制代码
def add(n,i):
    return n+i

def test():
    for i in range(4):
        yield i

g=test()
for n in [1,10]:
    g=(add(n,i) for i in g)
# n = 1
# g=(add(n,i) for i in test())
# n = 10
# g=(add(10,i) for i in (add(10,i) for i in test()))

print(list(g))  # [20, 21, 22, 23]
posted @ 2017-11-08 15:23  邯城吴彦祖  阅读(172)  评论(0编辑  收藏  举报