yiruia的个人博客分享 http://blog.sciencenet.cn/u/yiruia

博文

Day15生成器函数进阶

已有 1123 次阅读 2020-3-5 21:38 |系统分类:科研笔记

一、使用生成器的方式

def generator():
    print(123)
    yield 1
    print(456)
    yield 2
g = generator()
ret  = g.__next__()
print('***',ret)
ret  = g.__next__()
print('***',ret)
'''
123
*** 1
456
*** 2
'''

1、send

  1. send获取下一个值的效果和next基本一致,只是在获取下一个值的时候,给上一个yield的位置传递一个数据。

  2. 使用send的注意项:

(1)第一次使用生成器的时候,是使用next获取第一个值

(2)最后一个yield不能接收外部的值,最后一个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') # send的效果和next一样
print('***',ret)
'''
123
*** 1
~~~ hello
456
*** 2
'''

c. 练习题

# 获取移动平均值

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

avg_g = average()
avg_g.__next__()
avg1 = avg_g.send(10)
avg1 = avg_g.send(20)
print(avg1)
def init(func): # 装饰器————激活函数
    def inner(*args,**kwargs):
        g = func(*args,**kwargs) # g = average()
        g.__next__()
        return g
    return inner
@init # average = init(average) =inner
def average():
    sum = 0
    count = 0
    avg = 0
    while True:
        num = yield avg
        sum += num
        count += 1
        avg = sum/count

avg_g = average()
ret = avg_g.send(10)
print(ret)
ret = avg_g.send(20)
print(ret)


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)

改进:

def generator():
    a = 'abcde'
    b = '12345'
    yield from a #从容器中取的值集体返回
    yield from b
g = generator()
for i in g:
    print(i)

二、生成器的表达式

egg_list=[]
for i in range(10):
    egg_list.append('鸡蛋%s'%i)
print(egg_list)

(一)列表推导式,表达比较简洁

格式:值 for循环

egg_list = ['鸡蛋%s'%i for i in range(10)] #列表推导式
print(egg_list)
print([i for i in range(10)])
print([i*i for i in range(10)])

(二)生成器表达式

g = (i for i in range(10))
print(g)
for i in g:
    print(i)

(三)列表推导式和生成器表达式的区别:

1、括号不一样,列表推导式是[],而生成器是()。

2、返回值不一样,列表推导式是一次性把内容全部呈现,而生成器表达式是随用随取,几乎不占用内存。

如:

老母鸡 = ('鸡蛋%s'%i for i in range(10)) # 生成器表达式生成的是一个生成器,需要的时候要一个一个取。
print(老母鸡)
for 蛋 in 老母鸡:
    print(蛋)
g = (i*i for i in range(10))
print(g)
for i in g:
    print(i)

(四)各种推导式

1、列表推导式

(1)[每一个元素或是和元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] #遍历之后挨个处理

[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] #筛选功能

# 30以内所有能被3整除的数
ret = [i for i in range(30) if i%3 == 0] # 完整的列表推导式
print(ret)
# 30以内所有数的平方
ret = [i**2 for i in range(30) if i%3 == 0]
print(ret)

(2)找嵌套列表中名字含有两个e的元素

先for外面的大列表,再for里面的小列表

names = [['Tom','Billy','Jefferson','Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
ret =  [name for lis in names for name in lis if name.count('e')>=2]
print(ret)

(3)列表的生成器表达式

只是把列表推导式的[]换成()

2、字典推导式

例1、将一个字典的key和value对调

mcase = {'a':10, 'b':34}
mcase_frequency = {mcase[k]: k for k in mcase}
print(mcase_frequency)

例2、合并大小写对应的value值,将k统一成小写

mcase = {'a':10, 'b':34, 'A':7, 'Z':3}
mcase_frequency = {k.lower():mcase.get(k.lower(),0) + mcase.get(k.upper(), 0) for k in mcase.keys()}
print(mcase_frequency) #列表生成器表达式首先从for 开始看
d={'a':10}
print(d.get('b',2)) #若取不到'b'则返回2

3、集合推导式,集合能够自动对结果去重

例 计算列表中每个值的平方

squared = {x**2 for x in [1,-1,2]}
print(squared)
'''
{1, 4}
'''

4、各种推导式(如列表、字典、集合),将[]变成()就成了生成器。

  • 遍历操作

  • 筛选操作

三、本章小节

1、可迭代对象:

  •     拥有__iter__方法

  •     特点:惰性运算,不找它要值的时候,它不工作

  •     数据类型:range、dict、list、set

2、迭代器Iterator

拥有__iter__方法和__next__方法

3、生成器Generator:

  • 本质:迭代器,所以拥有__iter__方法和__next__方法

  • 特点:循环运算 开发者自定义

4、使用生成器

  • 生成器中的数据只能取一次,取完就没了

  • 惰性运算,不找他取值,他就不工作





https://blog.sciencenet.cn/blog-3405644-1221992.html

上一篇:Day14 迭代器和生成器
下一篇:Day16 重要的内置函数
收藏 IP: 223.91.46.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-5-20 03:11

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部