本章内容:

  • 列表生成式
  • 生成器
  • yield
  • 迭代器

列表生成式

当我们要定义一个列表的时候,我们通常用这种方式a = [1,2,3],但是如果我们定义了一个比较长的列表的时候,手动定义列表就会比较麻烦,这是我们通常的做法就是利用循环的手段来创建列表,例如创建如下的列表:

L = [0,1,4,9,16,25,36,49,64,81]

L = []
for x in range(1, 11):
L.append(x*x)

  这样我们就创建了一个较长的列表。

但是这样写,我们用了三行代码,其实我们可以用一行代码就代替了它:

L = [i*i for i in range(1,11)]

  这就是列表生成式。

前面的i*i是运算式,也可以用函数,然后后面加上一个for循环就可以了。

其实我们不难看出,for循环和列表生成式的关系,如下图:

for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:

[x * x for x in range(1, 11) if x % 2 == 0]
#结果为:
#[4, 16, 36, 64, 100]

还可以使用两层循环,可以生成全排列:

[m + n for m in 'ABC' for n in 'XYZ']
#结果为:
#['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

三层用的就比较少了。

生成器

上面的列表生成式的最外面是用中括号括起来的,如果把中括号变成小括号,也就是这样:

L = (i*i for i in range(1,11))

这样就是一个生成器了。

那么生成器有什么好处呢?

我们用列表生成式直接生成列表后,列表会直接放在内存中等待被使用。但是如果列表过于长了,但是我们暂时又用不到全部的元素,就会造成内存的浪费。生成器的好处就在于(i*i for i in range(1,11))这句话执行完毕后将返回一个算法给L,并不是直接将所有的数据放到内存中,当我们访问数据时,生成器就会根据算法现生成我们需要的书库,这样就避免了内存的浪费。

但是生成器不能像列表一样a[100]这样直接取出某个数据,因为生成器还没有访问到第100个元素。生成器其实就像一个递推公式一样,想要知道第100个元素是什么,就必须要先知道第99个元素是什么,以此类推...

下面用生成器生成一个列表并且遍历所有的数据

L = (i*i for i in range(1,11))
for i in L:
print(i)

也可以一个一个数据的访问,调用生成器中下一个数据

a = (i*i for i in range(1,11))
a.__next__() #这样就调用了下一个数据

并且生成器也只有一个方法,就是__next__()方法,只能往下走,不能回头。

yield

先来看一个菲波那切数列的迭代算法。

def fib(max):
n,a,b = 0,0,1
while n<max:
#print(b) #如果用print,那么这个函数就会直接输出数列的所有值
yield b #如果用yield,那么这个函数就会变成一个生成器
a, b = b, a + b
n = n + 1
return '---done---' #如果程序抛异常,就会返回这个信息

yield可以保存当前循环的状态,然后可以先做其他的事情,做完其他的事情,可以回来继续进行下一个循环。

yield的一个稍微复杂的应用 - 利用yield模拟多线程

import time
def consumer(name):
print("%s 准备吃包子了!" %name)
while True:
baozi = yield
print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
#当函数中有yield时,这个函数就会变成一个生成器
c = consumer('lisi') #将这个生成器赋值给c
c.__next__() #然后执行一次这个生成器,但是一次调用只会执行到含有yield的语句前面,
# 因为yield可以暂停并保存当前的状态,一到yield就会暂停,所以while循环里面的输出语句没有执行
c.send('猪肉') #send()函数,用来向yield里面传值,然后继续执行一次,直到再次碰到yield时就会再次暂停
#注意,第一次执行时一定要执行__next__()函数,后面才可以执行send()函数
c.send('牛肉') #再次传值,再次执行while里面的语句,注意,不会执行上面的print("%s 准备吃包子了!" %name)语句
c.send('niurou') #再次传值,再次执行while里面的语句
c.__next__() #这里再次调用__next__()函数,同样还是执行while里面的输出语句,但是不会向yield里面传值

上面是手动执行这个生成器,下面写一个函数来调用这个生成器。

import time
def consumer(name):
print("%s 准备吃包子了!" %name)
while True:
baozi = yield
print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
def producer():
c = consumer('A')
c2 = consumer('B')
c.__next__()
c2.__next__()
print('老子开始准备做包子了')
for i in range(10):
time.sleep(1)
print('做了一个包子,分两半')
c.send(i)
c2.send(i)
producer()
#这样就是一边做包子,一边吃包子了

迭代器

可以被next()函数调用并不断返回下一个值的对象成为迭代器:Iterator。

可以使用isinstance()判断一个对象是否是Iterator对象或者Iterable对象

from collections import Iterator    #需要先导入这个模块
isinstance((x for x in range(10)),Iterator)
#第一个参数为想要判断的东西,第二个参数是想要判断的类型
isinstance({},Iterator)
from collections import Iterable
isinstance((),Iterator)
isinstance('abc',Iterator)

生成器都是Iterator对象,但是list、dict、str虽然是Iterator,却不是Iterator。
把list、dict、str等Iterable变成Iterator可以使用iter()对象。

isinstance(iter([]),Iterator)   #这样结果就是True了
#例子
a = [1,2,3]
b = iter(a)
b.__next__()

Python学习之路7 - 生成器&迭代器的更多相关文章

  1. python学习之路------你想要的都在这里了

    python学习之路------你想要的都在这里了 (根据自己的学习进度后期不断更新哟!!!) 一.python基础 1.python基础--python基本知识.七大数据类型等 2.python基础 ...

  2. python学习之路-day2-pyth基础2

    一.        模块初识 Python的强大之处在于他有非常丰富和强大的标准库和第三方库,第三方库存放位置:site-packages sys模块简介 导入模块 import sys 3 sys模 ...

  3. Python学习之路-Day2-Python基础3

    Python学习之路第三天 学习内容: 1.文件操作 2.字符转编码操作 3.函数介绍 4.递归 5.函数式编程 1.文件操作 打印到屏幕 最简单的输出方法是用print语句,你可以给它传递零个或多个 ...

  4. Python学习之路-Day2-Python基础2

    Python学习之路第二天 学习内容: 1.模块初识 2.pyc是什么 3.python数据类型 4.数据运算 5.bytes/str之别 6.列表 7.元组 8.字典 9.字符串常用操作 1.模块初 ...

  5. Python学习之路-Day1-Python基础

    学习python的过程: 在茫茫的编程语言中我选择了python,因为感觉python很强大,能用到很多领域.我自己也学过一些编程语言,比如:C,java,php,html,css等.但是我感觉自己都 ...

  6. python学习之路网络编程篇(第四篇)

    python学习之路网络编程篇(第四篇) 内容待补充

  7. Python学习之路【第一篇】-Python简介和基础入门

    1.Python简介 1.1 Python是什么 相信混迹IT界的很多朋友都知道,Python是近年来最火的一个热点,没有之一.从性质上来讲它和我们熟知的C.java.php等没有什么本质的区别,也是 ...

  8. python 学习之路开始了

    python 学习之路开始了.....记录点点滴滴....

  9. python学习之路,2018.8.9

    python学习之路,2018.8.9, 学习是一个长期坚持的过程,加油吧,少年!

随机推荐

  1. js基础(闭包)

    1. "闭包就是跨作用域访问变量." [示例一] var name = 'wangxi' function user () { // var name = 'wangxi' fun ...

  2. 1015 德才论(sort、结构体vector)

    题目: 宋代史学家司马光在<资治通鉴>中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人.凡取人之术,苟不得圣人,君子而与之,与其得小人,不 ...

  3. Linux各个文件及其含义

    树状目录结构: 以下是对这些目录的解释: /bin:bin是Binary的缩写, 这个目录存放着最经常使用的命令. /boot:这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像 ...

  4. 偏前端--之小白学习本地存储与cookie

    百度了很多都是讲的理论,什么小于4kb啊之类的,小白看了一脸懵逼复制到html中为什么没效果!!哈哈.我来写一个方便小白学习. 贴图带文字描述,让小白也运行起来,然后自己再去理解... 1. cook ...

  5. node 借助Node Binary管理模块“n”更新

    Node.js的版本频繁变化,如果有模块不能在你当前的Node版本上使用,需要升级Node环境 1)首先:查看当前node版本:node –v 2)安装n模块:npm install -g n 3)检 ...

  6. shell的奇淫巧技--自动化脚本(sed命令)

    使用场景:前段时间交易所项目需要在服务器上用到 根据websocket推送价格数据,在交易所内进行下单撤单处理,但是由于有多个交易对,在服务器上部署时候,略显繁琐.(撮合引擎同样有此问题,可以一并解决 ...

  7. Alluxio原理和应用场景随笔

    上周末有幸参加了Alluxio(之前也叫Tachyon),七牛云和示说网举办的Alluxio上海Meetup,之前我并没有在真实应用场景中使用过Alluxio,对其适用的应用场景一直报怀疑态度.自信聆 ...

  8. python 装饰器和软件目录规范一

    1.装饰器和迭代器的概念. 装饰器本质是一个函数,是为其他函数添加附加功能. 原则:不修改原函数源代码 不修改原函数的调用方式 2.装饰器的简单应用 # Author : xiajinqi impor ...

  9. mysql secure_file_priv 文件读写问题

    secure_file_priv特性 使用 show global variables like '%secure%'; 查询显示 secure_file_priv的值为null,那么secure_f ...

  10. Myeclipse破解总结

    今天安装svn,Myeclipse莫名的崩了,然后就重装,然后不知为什么一直失败...经过无数次尝试,终于成功,应该是把这个破解过程遇到的所有问题都遇到了吧.有个别细节我没尝试,但以下总结用于Myec ...