day14 生成函数的进阶

一、上节回顾:

1、可迭代对象:惰性运算          拥有__iter__方法

2、迭代器:                              拥有__iter__和__next__方法

3、生成器:惰性运算,开发者自定义   本质:迭代器 所以拥有__iter__和__next__方法

     惰性运算:不取值就不计算  且每一个值只能被取一次,取完为止

     生成器的优点:延迟计算,一次返回一个结果,也就是说,它不会一次生成所有的结果,这对于大数据处理非常有用

生成器------迭代器:节省内存

1)生成器函数:

   带有yield 关键字

   执行函数之后的返回值是生成器,函数内的代码并不会真正执行

   想让生成器吐出数据,需要使用next 方法,send, for循环

二、新内容

1、生成器的调用例子 取用:cloth

def cloth():
    for i in range(100):
        yield "衣服%s"%i
g=cloth()
# 方法一
# for i in g:
#     print(i)
# 方法二
for i in range(100):
    print(g.__next__())
cloth

2、监听文件末尾追加的例子

调用生成器并不执行,当取用的时候才会执行def下面的内容(Windows系统的时候才可以使用)

def tail():
    f=open("你好.bak","r",encoding="utf-8")
    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.strip())
生成器(监听文件)

3、send  和next 的范围是一样的

     (1)从哪一个yield开始接着执行,就把一个值传给了那个yield

    (2)send 不能用在第一个触发生成器,触发生成器第一个必须是__next__()

     (3)生成器函数中有多少个yield就必须有多少个next+send

def func():
    print("*"*10)
    a=yield 5
    print(a)
    yield  10
g=func()
num=g.__next__()
print(num)
num2=g.send("alex")
print(num2)
# **********
# 5
# alex
# 10
send 例子
def averager():
    total=0.0
    count=0
    average=None
    while True:
        term=yield  average
        total+=term
        count+=1
        average=total/count
g_avg=averager()
g_avg.__next__()
print(g_avg.send(10))
print(g_avg.send(20))
print(g_avg.send(30))
# 10.0
# 15.0
# 20.0
利用 send(银行七日化利息)

4、补充:python3 之后有的这个功能:yield from a

def func():
    a="AB"
    b="CD"
    yield from a
    #for i in a:yield i
    yield from b
    #for i in b:yield i
g_func=func()
for i in g_func:
    print(i)
yield from 的使用

5、触发执行的方式

(1)生成器.__next__()

 (2)生成器.send()        

      send(None)==__next__().  

      send在next的基础上传一个值到生成器函数的内部

      send 操作不能用在生成器使用的第一次

      以上两个执行几次拿几个数据,可能会遇到取完报错

(3)for循环   每次取一个,取完为止。for循环不会报错

6、总结:

    生成器函数:生成一个生成器的函数

    生成器的本质:参数迭代器

    生成器函数的特点:(1)带有yield 关键字 (2)且调用之后,函数内的代码不执行

 触发执行的方式:(1)next  (2)send  (3)for 循环

三、各种推导式

 1、列表推导式:

y=[1,2,3,4,5,6,7]
# 方法一
# x=[]
# for i in y:
#     x.append(i**2)
# print(x)
# 方法二
x=[i**2 for i in y]
print(x)
# [1, 4, 9, 16, 25, 36, 49]
列表推导式1
# x=[]
# for i in range(100):
#     x.append(i/2)
# print(x)
x=[i/2 for i in range(100)]
print(x)
列表推导式2

2、生成器表达式 (生成器表达式+for循环节省内存 推荐使用)

#列表推导式
y=[1,2,3,4,5,6]
x=[i**2 for i in y]  #[  ]
print(x)
#生成器表达式
y=[1,2,3,4,5,6]
g=(i**2 for i in y)  #(  )
print(g)
for i in g:
    print(i)
列表推导式和生成器表达式
l=["鸡蛋%s"%i for i in range(10)]
print(l)
lmuji=("鸡蛋%s"%i for i in range(10))
for egg in lmuji :
    print(egg)
鸡蛋和母鸡的理论

 3、补充:

并不是所有的都可以转换

g.__next__()==next(g )
g.__iter__()==inter(g)

4、30以内能被3整除的数的平方 列表推导式的例子

# 30以内能被3整除的数的平方
# x=[i**2 for i in range(30) if i%3==0]
# print(x)
def square(x):
    return  x**2
x=[square(i) for i in range(30) if i%3==0]
print(x)
30以内能被3整除的数的平方

5、字典推导式

dic={"a":10,"b":34}
dic_fre={dic[k]:k for k in dic}
print(dic_fre)
#{10: 'a', 34: 'b'}   key value 对换
key value 对换
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}
print(mcase_frequency)
#{'a': 17, 'b': 34, 'z': 3}
字典中大小写相加

6、集合的推导式 去重

squared={x**2 for x in [1,-1,2]}
print(squared)
#set([1,4])
集合的去重

面试题:

原文地址:https://www.cnblogs.com/number1994/p/7979141.html