• 生成器-next(),__next()__,yield,send(),协程方法


    1.生成器(generator)

    通过列表生成式(列表推导式),我们可以直接创建一个列表

    但是,受到内存限制,列表容量肯定是有限的,而且创建一个100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间就白白浪费了。

    所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?

    这样就不必创建完整的list,从而节省大量的空间,在Python中,这种一边循环一边计算的机制,称为生成器。

    注意:列表推导式和生成器的区别,生成器是用()的,而列表推导式是用[]

    两种通知生成器生成元素的方式:

    方式1:调用__next__()

     1 newlist = [x*3 for x in range(10)]
     2 print(newlist)
     3 print(type(newlist))
     4 
     5 g = (x*3 for x in range(10))
     6 print(g)
     7 print(type(g))
     8 
     9 # 每调用一次,就生成一个元素(通过调用__next__())
    10 print(g.__next__())
    11 print(g.__next__())
    12 print(g.__next__())

    方式2:使用系统自带的next()调用,系统内置的函数next(生成器对象),每调用一次,next()会产生一个元素

     1 # 每调用一次,就生成一个元素(通过调用__next__())
     2 print("=========使用__next()__方法=========")
     3 print(g.__next__())
     4 print(g.__next__())
     5 print(g.__next__())
     6 
     7 
     8 # 使用系统自带的next()方法
     9 print("================使用next()方法================")
    10 print(next(g))
    11 print(next(g))

    生成器中使用yield

     1 # 只要在函数中有yield关键字,说明这个函数不是函数了,就变成了生成器了
     2 """
     3 步骤:
     4     1.定义一个函数,函数中使用yield关键字
     5     2.调用函数,接收调用的结果
     6     3.得到的结果就是生成器
     7     4.可以借助于next()或__next()__得到元素
     8 """
     9 
    10 def func():
    11     n = 0
    12     while True:
    13         n += 1
    14         yield n   # 类似于return n,同时yield也有暂停的功能
    15 
    16 # 得到一个生成器对象
    17 g = func()
    18 print(type(g))
    19 
    20 # 使用next()执行函数里面的内容
    21 print(next(g))
    22 # 第二次执行next()时候,就在while循环里面执行了,因为yield有暂停功能
    23 print(next(g))
    24 print(next(g))
    25 print(next(g))

     用yield生成斐波那契数列

     1 def fib(length):
     2     a, b = 0, 1
     3     n = 0
     4     while n < length:
     5         yield b
     6         a, b = b, a+b
     7         n += 1
     8 
     9         
    10 g = fib(8)
    11 print(next(g))
    12 # 每次从yield暂停的位置执行
    13 print(next(g))
    14 print(next(g))
    15 print(next(g))
    16 print(next(g))

    在生成器中return ,return后面的信息会出现在异常里面

     1 def fib(length):
     2     a, b = 0, 1
     3     n = 0
     4     while n < length:
     5         yield b
     6         a, b = b, a+b
     7         n += 1
     8 
     9     return '没有更多元素了!'   # return就是在得到StopIteration后的提示信息
    10 
    11 
    12 g = fib(8)
    13 print(next(g))
    14 # 每次从yield暂停的位置执行
    15 print(next(g))
    16 print(next(g))
    17 print(next(g))
    18 print(next(g))
    19 print(next(g))
    20 print(next(g))
    21 print(next(g))
    22 print(next(g))

     生成器的send()方法

     1 """
     2 生成器方法:
     3     1.__next()__:获取下一个元素
     4     2.send(value):向每次生成器调用中传值,注意:第一次调用使用send(None)
     5 """
     6 def gen():
     7     i = 0
     8     while i < 5:
     9         temp = yield i  # return i + 暂停
    10         print("temp:", temp)
    11         i += 1
    12     return '没有更多数据了!'
    13 
    14 
    15 g = gen()
    16 
    17 print(g.send(None))
    18 n1 = g.send('呵呵')
    19 print("n1:", n1)
    20 n2 = g.send('哈哈')
    21 print("n2:", n2)

     协程使用yield

     1 # 进程 > 线程 >进程
     2 # 当在一个线程里需要做多个任务的话,就需要引入协程,就是任务之间交替进行(多个任务之间的切换)
     3 
     4 def task1(n):
     5     for i in range(n):
     6         print("正在搬第{}块砖".format(i))
     7         yield None
     8 
     9 
    10 def task2(n):
    11     for i in range(n):
    12         print("正在听第{}首歌".format(i))
    13         yield None
    14 
    15 
    16 g1 = task1(5)
    17 g2 = task2(5)
    18 
    19 while True:
    20     try:
    21         g1.__next__()
    22         g2.__next__()
    23 
    24     except:
    25         print("循环结束")
    26         break

     总结:

    定义生成器的方式:

    1.通过列表推导式的方式

      g=(x+1 for x in range(6))

    2.函数+yield

      def func():

        ...

        yield 

      g = func()  # 此时g就是生成器

    3.产生元素

      (1)next(generator),每调用一次,就会产生一个新的元素,如果元素产生完毕,再次调用的话,就会产生异常,StopIteration

      (2)生成器自己的方法:g.__next()__,g.send(value)

    4.生成器的应用

      协程

  • 相关阅读:
    CSS 背景
    CSS padding 属性
    CSS border 属性和 border-collapse 属性
    CSS margin 属性
    IEnumerable<T> 接口和GetEnumerator 详解
    discuz! X3.4特殊字符乱码解决方案
    Discuz通过修改文章标题更好的实现SEO的方法
    关于Discuz x3.3页面空白解决方法
    discuz x3.3标题的最少字数限制设置方法
    discuz网站前端代码优化思路
  • 原文地址:https://www.cnblogs.com/GumpYan/p/12347342.html
Copyright © 2020-2023  润新知