Python 基础 - Day 4 Learning Note - Generator 生成器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 基础 - Day 4 Learning Note - Generator 生成器相关的知识,希望对你有一定的参考价值。

列表生成器/列表解析 list comprehension

  • 简单灵活地创建列表,通常和lambda(), map(), filter() 一起使用
  • 通过列表生成式, 直接创建列表。但是,收到内容限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问几个元素,那其他的就白占空间。列表生成器能够一边循环一边计算,大大节省大量的空间。是生成器的一种。 

  • 只有调用,才能生成。 不支持切片操作,只能通过__next()___一个个取数字。

基本语法

[expr for iter_var in iterable]
or
[expr for iter_var in iterable if cond_expr]

案例

技术分享
# example 1:
>>> [i*2 for i in range(10)]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# example 2: 迭代3行5列的矩阵
q = [(x+1, y+1) for x in range(3) for y in range(5)]
print(q)
list comp

 

生成器

定义

生成器是列表生成器的一个扩展。 在python中,这种一边循环一边计算的机制,称为生成器 generator; 每次计算一个条目后,把这个条目“生成“(yield)出来, 这个过程成为”延迟计算“ (lazy evaluation),所以在使用内存上更有效。在语法上,生成器就是一个带yield语句的函数。 

应用:

1. 调用函数中的一个值并跳出函数,下次进入继续调用下个值。以下面斐波拉契Fibonacci数列为例:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b  # 知识点1 - yield的功能,返回一个值给调用者并暂停执行。
        a, b = b, a + b   # 重新赋值的过程, 左边的a,b是新生的, 右边的过去的值运算
        n = n + 1
    return "done"    # return 的作用是next调用时可能出现异常处理的返回值。

print(fib(10))  # 返回变为一个generator: <generator object fib at 0x0000026FAA8A78E0>

# 知识点2 - 调用元素的方式
f = fib(10)
for i in f:
    print(i)  # 用for循环,函数返回值done不会打印

# 知识点3 - next()调用出现异常的情况
g = fib(6)
while True:
    try:
        x = next(g)     # 内置方法,= __next__一样。 当达到一个真正的返回或者函数结束没有更多的值返回,一个StopIteration异常将会抛出。所以需要处理异常,通过try ... expect... 语句
        print(g:,x)
    except StopIteration as e:
        print(Generator return value: , e.value)   # e.value 返回的是 done

2. 协同程序。协同程序是可以运行的独立函数调用,可以暂停或者挂起,并从程序离开的地方继续或者重新开始。在有调用者和(被调用者)协同程序也有通信。举例来说,当协同程序暂停的时候,我们能从其中获得一个中间的返回值,当调用回到程序中时,能够传入额外或者改变了的参数,但仍能够从我们上次离开的地方继续,并且所有状态完整。生成器的作用是挂起返回出中间值并多次继续的协同程序。

技术分享
 1 #!usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # 通过yield实现在单线程的情况下实现并发运算的效果,或者; 典型的生产者 - 消费者模型.这是以后异步IO的雏形。
 4 
 5 import time
 6 
 7 
 8 def consumer(name):
 9     print(%s 准备吃包子啦 %name)
10     while True:
11         baozi = yield   # yield
12         print(包子[%s]来了,被[%s]吃了 %(baozi,name))
13 
14 
15 def producer(name):
16     c = consumer(A)   # 将函数变成生成器
17     c2 = consumer(B)
18     c.__next__()        # 第一次调用生成器
19     c2.__next__()
20     print(老子开始准备吃包子啦!)
21     for i in range(10):
22         time.sleep(1)
23         print("做了2个包子!")
24         c.send(i)   # send的作用是唤醒并给yield传值,next只是调用yield
25         c2.send(i)
26 
27 producer("alex")
最简单的协程 - 吃包子例子

 

Reference

1. Python之路,Day4 - Python基础4 (new版),http://www.cnblogs.com/alex3714/articles/5765046.html

2. 《Python 核心编程 V2》page 205 - 207; page 305 - 307

 

以上是关于Python 基础 - Day 4 Learning Note - Generator 生成器的主要内容,如果未能解决你的问题,请参考以下文章

学习PYTHON之路, DAY 4 - PYTHON 基础 4 (内置函数)

重修课程day7(python基础4之基础补充)

Day1_Python基础_4.Python安装

day4-python基础4 字符串操作

Python之路,Day4 - Python基础4

Python之路,day4-Python基础