13 生成器函数

主要内容:

1. 生成器:生成器的实质就是迭代器,在python中有三种方式可以获取生成器:

  通过生成器函数

  通过各种推导式来实现生成器

  通过数据的转换也可以实现生成器

2. 生成器函数

  a: 函数中包含了yield的就是生成器函数.

   注意:生成器函数被执行,获取的是生成器,而不是函数的执行

def fn():
    print("张杰")
    yield "谢娜"    #函数中包含yeild说明该函数不是一个普通的函数,而是生成器函数
    print("你好啊")
    yield "hi"
    print("明日之子")
    yield ‘pick田四火‘
s = fn()       #创建一个生成器
print(s.__next__())
print(s.__next__())
print(s.__next__())      #最后一个yield执行完毕,在执行yield会报错.
#return 直接返回函数结果,结束调用
#yeild  返回结果,可以让函数分段进行

  b: 注意

def func():
    print("张杰")
    yield "谢娜"    #函数中包含yeild说明该函数不是一个普通的函数,而是生成器函数
    print("明日之子")
    yield ‘pick田四火‘
g1 = func()                  #表示两个相同的生成器,第一个从头开始指向下一个元素,第二个也是从头开始指向元素.
g2 = func()
print(g1.__next__())        #张杰谢娜
print(g1.__next__())        #明日之子,田四火
print("==============")
print(g2.__next__())        #张杰谢娜

  c: 生成器的优点,可以节约内存,

  例题:例如老男孩教育要给每个培训的学员定制一套衣服,共10000套.

def fn():
    lst = []
    for i in range(1,10001):
        lst.append(‘衣服%s‘ % i)
    return lst
s = fn()
print(s)

  缺点:一次性全部拿出来,会很占用内存.

def fn():
    lst = []
    i = 1
    while i < 100001:
        yield ‘衣服%s‘ % i
        i = i + 1
g = fn()
print(g.__next__())
print(g.__next__())
print(g.__next__())

  使用生成器.一次就一个,用多少生成多少,生成器是一个一个的指向下一个,不会回去,__next__()到哪,指针就指到哪.下一次继续或许指针指向的值

  d: 拿到的是生成器. 生成器的本质是迭代器. 迭代器可以被迭代 生成器可以直接for循环

def func():
    yield 11
    yield 22
    yield 33
g = func()    #拿到的是生成器,生成器的本质是迭代器,迭代器可以被迭代,生成器可以直接for循环
for i in g:
    print(i)

  e: list[g]

def func():
    yield 11
    yield 12
    yield 13
    yield 14
g = func()           #获取生成器
lst = list(g)        #括号里必须为可迭代对象
print(lst)

3. send: send和__next__一样,都可以让生成器执行到下一个yield.

  send和__next__的区别:

    send():也可以让生成器向下执行一次,给上一个yield传一个值,第一个不能用send,最后一个也不要传值.

    __next__:可以使生成器向下执行一次.

def eat():
    print("我吃什么啊")
    a =  yield  "馒头"
    print("a=",a)
    b =  yield  "大饼"
    print("b=",b)
    c =  yield  "韭菜盒子"
    print("c=",c)
    yield  "GAME OVER"
gen = eat()      # 获取?成器
print(gen. __next__ ())      #到yield结束,返回馒头
print(gen.send("胡辣汤"))    #可以给上一个yield传值,a = 胡辣汤
print(gen.send("狗粮"))      #可以给上一个yield传值,b = 狗粮
print(gen.send("猫粮"))      #可以给上一个yield传值,c = 猫粮

4. 列表推导式

语法:[最终结果 for     变量   in  可迭代对象  ]

语法:[最终结果  for   变量   in  可迭代对象  if 条件]

  生成列表,里面装1-14数据

    普通模式

li = []
for i in range(1,15):
    li.append(‘python%s期‘ % i)
print(li)

    采用推导式

li = [‘python%s期‘ % i for i  in range(1,15)]
print(li)
# [‘python1期‘, ‘python2期‘, ‘python3期‘, ‘python4期‘, ‘python5期‘, ‘python6期‘, ‘python7期‘, ‘python8期‘, ‘python9期‘, ‘python10期‘, ‘python11期‘, ‘python12期‘, ‘python13期‘, ‘python14期‘]

  获取100以内能被3整除的数的平方

li = [i*i for i in range(101) if i % 3 == 0 ]
print(li)

  寻找名字中带有两个e的人的名字

names = [[‘Tom‘, ‘Billy‘, ‘Jefferson‘ , ‘Andrew‘ , ‘Wesley‘ , ‘Steven‘ ,
‘Joe‘],[‘Alice‘, ‘Jill‘ , ‘Ana‘, ‘Wendy‘, ‘Jennifer‘, ‘Sherry‘ , ‘Eva‘]]
lst = [name for first in names for name in first if name.count("e") == 2]
print(lst)

5. 字典推导式

  dic = {"a":"b", "c":"d"},把字典中的key和value互换:

dic = {‘a‘:‘b‘,‘c‘:‘d‘}
new_dic = { dic[key]:key for key in dic}
print(new_dic)

  lst1作为key,lst2作为value

lst1 = ["alex", "wusir", "taibai", "ritian"]
lst2 = [‘sb‘, "很色", "很白", "很牛"]
dic = {lst1[i]:lst2[i] for i in range(len(lst1))}      #取他们的索引
print(dic)

6. 集合推导式

lst = [‘马化腾‘,‘马化腾‘,‘王建中‘,‘张建忠‘,‘张雪峰‘,‘张雪峰‘]
s = {i for i in lst}
print(s)

7. 生成器表达式

  把列表推导式[]变成(),就成为生成器表达式

  格式(最终结果  for 变量 in 可迭代对象)

gen = ("麻花藤我第%s次爱你" % i for i in range(10))
print(gen)                #<generator object <genexpr> at 0x0000021314580F68>

  打印的结果是一个生成器,我们可以用for循环来循环这个生成器.

gen = ("麻花藤我第%s次爱你" % i for i in range(10))
for i in gen:
    print(i)

  生成器表达式也可以进行筛选:

gen = (i for i in range(100) if i % 3 == 0)
for e in gen:
    print(e)

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

  a: 列表推导式比较耗内存,一次性加载,生成器表达式几乎不占用内存,使用的时候才分配和使用内存.

  b: 得到的值不一样,列表推导式得到的是一个列表,生成器表达式获取的是一个生成器.

  形象的说明:列表推导式:直接拿到一筐子鸡蛋,生成器表达式:拿到一个老母鸡,需要的时候母鸡就给你下鸡蛋.

  生成器的惰性机制:

    生成器只有在访问的时候才取值,说白了,你找他要,他才给你,不找他要,他不会执行.

# 生成器的惰性机制:
def func():
    print(111)
    yield 222
g = func()             #通过生成器函数获得的生成器
g1 = (i for i in g)   #通过生成器表达式获得的生成器g1
g2 = (i for i in g1)  #生成器g2
print(list(g))     #获取g中的数据,这是func()才会执行,打印111,获取到222,g完毕.
print(list(g1))    #获取g1中的数据,g1 的数据来源g,但是g已经取完了,g1也就没有数据了.
print(list(g2))

  有关生成器表达式的惰性机制的一道面试题

def add(a, b):
    return a + b
def gen():
    for r_i in range(4):
         yield r_i
g = gen()
for n in [2, 10]:
    g = (add(n, i) for i in g)  #生成器的惰性机制,生成器只有在访问的时候才取值,说白了,你找他要,他才给你值.不找他要不会给你的
print(list(g))                   #不到最后不会拿值:惰性机制.

  

def add(a, b):
    return a + b
def test():
    for r_i in range(4):
         yield r_i
# g = test()
    # g = (add(n, i) for i in g)  #生成器的惰性机制,生成器只有在访问的时候才取值,说白了,你找他要,他才给你值.不找他要不会给你的
    g = (add(10, i) for i in (add(10, i) for i in 0,1,2,3)  #第二次执行的时候替换后面的g
    g = (add(10, i) for i in 10,11,12,13
print(list(g))
# lst(g) = [20,21,22,23]

  

  

  

原文地址:https://www.cnblogs.com/gyh412724/p/9328799.html

时间: 2024-10-14 02:04:57

13 生成器函数的相关文章

13、生成器函数

一.生成器函数#生成器函数:只要函数体包含yield关键字,该函数的执行结果就是生成器函数#生成器就是迭代器 # def foo():# return 1# return 2# return 3# return 4## res1=foo()# print(res1)## res2=foo()# print(res2) # def foo():# print('first')# yield 1# print('second')# yield 2# print('third')# yield 3#

ES6生成器函数generator

generator是ES6新增的一个特殊函数,通过 function* 声明,函数体内通过 yield 来指明函数的暂停点,该函数返回一个迭代器,并且函数执行到 yield语句前面暂停,之后通过调用返回的迭代器next()方法来执行yield语句.如下代码演示: function* generator() { yield 1; yield 2; yield 3; } var gen = generator(); 如上代码:generator函数的调用方法与普通函数一样,也是在函数名后面加上一对圆

Day 21 三元表达式、生成器函数、列表解析

知识点程序: 1 #! /usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # __author__ = "DaChao" 4 # Date: 2017/6/16 5 6 l = [i for i in range(100) if i%2 > 0] 7 print(l) 8 9 ########################### 10 #生成器 generator!!! 模拟tail grep功能 11 ##############

取代Promise的Generator生成器函数

接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还有一种常用的解决方案,它就是Generator生成器函数.顾名思义,它是一个生成器,它也是一个状态机,内部拥有值及相关的状态,生成器返回一个迭代器Iterator对象,我们可以通过这个迭代器,手动地遍历相关的值.状态,保证正确的执行顺序. 一.简单使用 1. 声明 Generator的声明方式类似一般的函数声明,只是多了个*号,并

python迭代器和生成器(3元运算,列表生成式,生成器表达式,生成器函数)

1.1迭代器 什么是迭代器: 迭代器是一个可以记住遍历的位置对象 迭代器对象从集合的第一个元素元素开始访问,直到所有元素被访问完结束,迭代器只能往前不会后退. 迭代器有两个基本方法:iter ,next 方法 内置函数iter(),next()  本质上都是用的对象.__iter__(),__next__()的方法 内置函数 iter(iterable),表示把可迭代对象 变成迭代器(iterator) 内置函数next(iterator) ,表示查看下一次迭代的值(当然也可以用 iterato

十四:生成器函数和迭代器函数

一:列表生成器:就是在列表内部使用一条语句来生成一个列表. example 1: 列表生成器示例 1 # 列表生成: 把可迭代对象中的每一个元素进行操作的结果放在列表中 2 3 s = [x * x for x in range(5)] 4 5 6 # 操作也可以是一个函数 7 8 def f(x): 9 return x * x 10 11 s = [f(x) for x in range(5)] 二:生成器函数:生成器函数与一般的函数有一个显著的不同,对于一般的函数,会把所有的结果一次性返回

python 第五章 迭代器,生成器,生成器函数

迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁.这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件 特点:访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容不能随机访问集合

生成器函数进阶

1.生成器函数进阶(一) 1 # 生成器函数进阶 2 3 def generator(): 4 print(123) 5 num = yield 1 # 当第一个__next__发生时,yiled 1先被执行,被返回,停在了这里,之后当send来了后,send的参数先赋值给了yield的左值,之后再执行下一个yield之前的代码 6 # send()获取yield值之前,会给上一个yield的位置传递一个参数数据,这个数据可以被上一个yield的左值接收 7 # 使用生成器的send()方法,就

生成器函数以及生产消费模型

1.生成器函数,即最终的输出用yield替代return,其他形式不变的函数,而且相比于return,输入yield函数不会立即停止 1 def test(): 2 print('你好') 3 return 10 4 def test_1(): 5 print('你好') 6 yield 10 7 a = test() 8 print(a) 9 b = test_1() 10 print(b) #<generator object test_1 at 0x00000000024F3570> 首