day 14 - 1 生成器

生成器

生成器
  生成器的本质就是迭代器
生成器的表现形式
  生成器函数
    生成器函数 —— 本质上就是我们自己写得函数
  生成器表达式
生成器函数:
  含有 yield 关键字的函数就是生成器函数
  特点:
    调用函数的之后函数不执行,返回一个生成器
    每次调用 next 方法的时候会取到一个值
    直到取完最后一个,在执行 next 会报错

从生成器中取值的几个方法
  1、next
  2、for
  3、数据类型的强制转换:占用内存 print(list(g))

生成器函数

我们先来看下普通函数

def generator():
    print(1)
    return 'a'
ret = generator()
print(ret)

接着来看生成器函数

#只要含有yield关键字的函数都是生成器函数
# yield 不能和 return 共用且需要写在函数内
def generator():
    print(1)
    yield 'a'
#生成器函数:在执行之后会得到一个生成器作为返回值
ret = generator()   #此处的 ret 是一个生成器而不是值了
print(ret)          #此处在同过原来的调用方法调用的是内存地址
print(ret.__next__())   #通过 .__next__() 来调用函数的输出内容

下面来看一个生成器函数的例子

#在取值时 会取到第一个 yield 时停止,然后等待下一次取值的动作开始,继续取值到下一个 yield 
def generator():
    print(1)
    yield 'a'
    print(2)
    yield 'b'
    print(3)
    yield 'c'
g = generator()

ret = g.__next__()  #单独执行第一次时:1 a
print(ret)
ret = g.__next__()  #即:可以控制执行的位置
print(ret)
ret = g.__next__()
print(ret)

for i in g:         #使用 for 循环也同样可以
    print(i)        #但 for 循环不可以控制执行位置

写一个函数 制造 200w 个娃哈哈

ef wahaha(*args):
    for i in range(2000000):
        yield "娃哈哈%s"%i
ret = wahaha(1000)

#调用
#for i in ret:
#    print(i)

#调用前 50 个
count=0
for i in ret:
    print(i)
    count+=1
    if count > 50:
        break
print(ret.__next__()) #这里一起执行会接着 for 循环调用 ret ,返回第 51个

监听文件输入的例子

#当检查到文件中有输入含有 python 字符时就会在屏幕上打印
def tail(filename):
    f = open(filename,encoding='utf-8')  #文件句柄
    while True:
        line = f.readline()
        if line.strip():
            yield line.strip()

ret = tail('D:/py/log/test.txt')
for i in ret:
    if 'python' in i:
        print('***',i)

生成器函数进阶

关键字 send 的使用

#send 获取下一个值的效果和 next 基本一致
#只是在获取下一个值的时候,给上一 yield 的位置传递一个数据
#使用 send 的注意事项
    # 第一次使用生成器的时候 要、必须用 next 获取下一个值
    # 最后一个 yield 不能接受外部的值

def generator():
    print(123)
    content = yield 1
    print('=====',content)
    print(456)
    yield 2

g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello')  #向函数 content 的位置传值
print('***',ret)

获取移动平均值(每次输入一个值都会计算出一个平均值)

10 20 30 10
10 15 20 17.5
avg = sum/count

def average():
    sum = 0
    count = 0
    avg = 0
    while True:
        num = yield avg
        sum +=num
        count += 1
        avg = sum/count

avg = average()
avgs = avg.__next__()
avgs = avg.send(10)
avgs = avg.send(30)
avgs = avg.send(60)
avgs = avg.send(60)
print(avgs)

 预激生成器的装饰器
获取移动平均值进阶与装饰器的使用

#装饰器的作用就是在用户使用时,少写一句 ret = g.__next__() 方便操作
def init(func):
    def inner(*args,**kwargs):
        ret = func(*args,**kwargs)
        ret.__next__()
        return ret
    return inner


@init
def average():
    sum =0
    count = 0
    avg = 0
    while True:
        num = yield avg
        sum += num
        count += 1
        avg=sum/count
        
avg = average()
ret = avg.send(10)
ret = avg.send(20)
ret = avg.send(60)
print(ret)
ret = avg.send(20)
ret = avg.send(20)
print(ret)

from 关键字的使用

#先来看一个 for 循环的例子,取出字符串中所有的单个字符
def generator():
    a = 'abcde'
    b = '12345'
    for i in a:
        yield i
    for i in b:
        yield i
g = generator()
for i in g:
    print(i)

#使用 from 关键字取出
def generator():
    a = 'abcde'
    b = '12345'
    yield from a
    yield from b

g = generator()
for i in g:
    print(i)

生成器的表达式

猜你喜欢

转载自www.cnblogs.com/ysging/p/10089807.html
今日推荐