Python中的列表生成式与生成器学习教程


Posted in Python onMarch 13, 2016

列表生成式
即创建列表的方式,最笨的方法就是写循环逐个生成,前面也介绍过可以使用range()函数来生成,不过只能生成线性列表,下面看看更为高级的生成方式:

>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

写列表生成式时,把要生成的元素x * x放到前面,后面跟for循环,就可以把list创建出来,十分有用,多写几次,很快就可以熟悉这种语法。
你甚至可以在后面加上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']

看一个简单应用,列出当前目录下所有文件和目录:

>>> import os
>>> [d for d in os.listdir('.')]
['README.md', '.git', 'image', 'os', 'lib', 'sublime-imfix', 'src']

前面也说过Python里循环中可以同时引用两个变量,所以生成变量也可以:

>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.iteritems()]
['y=B', 'x=A', 'z=C']

也可以通过一个list生成另一个list,例如把一个list中所有字符串变为小写:

>>> L = ['Hello', 'World', 'IBM', 'Apple']
>>> [s.lower() for s in L]
['hello', 'world', 'ibm', 'apple']

但是这里有个问题,list中如果有其他非字符串类型,那么lower()会报错,解决办法:

>>> L = ['Hello', 'World', 'IBM', 'Apple', 12, 34]
>>> [s.lower() if isinstance(s,str) else s for s in L]
['hello', 'world', 'ibm', 'apple', 12, 34]

此外,列表生成式还有许多神奇用法,说明请看注释:

#!/usr/bin/env python3 
# -*- coding: utf-8 -*- 
 
list(range(1, 11)) 
 
# 生成1乘1,2乘2...10乘10 
L = [] 
for x in range(1, 11): 
  L.append(x * x) 
 
# 上面太麻烦,看下面 
[x * x for x in range(1, 11)] 
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 
 
# 加上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'] 
 
# 列出当前目录下的所有文件和目录名 
import os 
[d for d in os.listdir('.')] # on.listdir可以列出文件和目录 
 
# 列表生成式也可以使用两个变量来生成list: 
d = {'x': 'A', 'y': 'B', 'z': 'C'} 
[k + '=' + v for k, v in d.items()] 
# ['x=A', 'z=C', 'y=B'] 
 
# 把一个list中所有的字符串变成小写 
L = ['Hello', 'World', 'IBM', 'Apple'] 
[s.lower() for s in L] 
# ['hello', 'world', 'ibm', 'apple'] 
 
L1 = ['Hello', 'World', 18, 'Apple', None] 
L2 = [s.lower() for s in L1 if isinstance(s, str)] 
print(L2) 
# ['hello', 'world', 'apple'] 
# isinstance函数可以判断一个变量是不是字符串

生成器
列表生成式虽然强大,但是也会有一个问题,当我们想生成一个很大的列表时,会非常耗时,并且占用很大的存储空间,关键是这里面的元素可能你只需要用到前面很少的一部分,大部分的空间和时间都浪费了。Python提供了一种边计算边使用的机制,称为生成器(Generator),创建一个Generator最简单的方法就是把[]改为():

>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x7fe73eb85cd0>

如果要一个一个打印出来,可以通过generator的next()方法:

>>> g.next()
0
>>> g.next()
1
>>> g.next()
4
>>> g.next()
9
>>> g.next()
16
>>> g.next()
25
>>> g.next()
36
>>> g.next()
49
>>> g.next()
64
>>> g.next()
81
>>> g.next()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
StopIteration

其实generator object也是可迭代的,所以可以用循环打印,还不会报错。

>>> g = (x * x for x in range(10))
>>> for n in g:
...   print n
...

这是简单的推算算法,但是如果算法比较复杂,写在()里就不太合适了,我们可以换一种方式,使用函数来实现。
比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, …
斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

def fib(max):
  n, a, b = 0, 0, 1
  while n < max:
    print b
    a, b = b, a + b
    n = n + 1

上面的函数可以输出斐波那契数列的前N个数,这个也是通过前面的数推算出后面的,所以可以把函数变成generator object,只需要把print b改为yield b即可。

def fib(max):
  n, a, b = 0, 0, 1
  while n < max:
    yield b
    a, b = b, a + b
    n = n + 1

如果一个函数定义中包含了yield关键字,这个函数就不在是普通函数,而是一个generator object。

>>> fib(6)
<generator object fib at 0x7fa1c3fcdaf0>
>>> fib(6).next()
1

所以要想调用这个函数,需要使用next()函数,并且遇到yield语句返回(可以把yield理解为return):

def odd():
  print 'step 1'
  yield 1
  print 'step 2'
  yield 3
  print 'step 3'
  yield 5

看看调用输出结果:

>>> o = odd()
>>> o.next()
step 1
1
>>> o.next()
step 2
3
>>> o.next()
step 3
5
>>> o.next()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
StopIteration

同样也可以改为for循环语句输出。例如:

def odd():
  print 'step 1'
  yield 1
  print 'step 2'
  yield 2
  print 'step 3'
  yield 3

if __name__ == '__main__':
  o = odd()
  while True:
    try:
      print o.next()
    except:
      break
Python 相关文章推荐
Linux下将Python的Django项目部署到Apache服务器
Dec 24 Python
ubuntu环境下python虚拟环境的安装过程
Jan 07 Python
python opencv设置摄像头分辨率以及各个参数的方法
Apr 02 Python
可能是最全面的 Python 字符串拼接总结【收藏】
Jul 09 Python
Python中GIL的使用详解
Oct 03 Python
详解Python连接MySQL数据库的多种方式
Apr 16 Python
python实现视频分帧效果
May 31 Python
linux下安装python3和对应的pip环境教程详解
Jul 01 Python
python实现从本地摄像头和网络摄像头截取图片功能
Jul 11 Python
Python-Tkinter Text输入内容在界面显示的实例
Jul 12 Python
python中update的基本使用方法详解
Jul 17 Python
python实现字符串和数字拼接
Mar 02 Python
jupyter安装小结
Mar 13 #Python
Ubuntu下安装PyV8
Mar 13 #Python
Python连接MySQL并使用fetchall()方法过滤特殊字符
Mar 13 #Python
深入讲解Python函数中参数的使用及默认参数的陷阱
Mar 13 #Python
编写Python小程序来统计测试脚本的关键字
Mar 12 #Python
使用Python内置的模块与函数进行不同进制的数的转换
Mar 12 #Python
Python语言的面相对象编程方式初步学习
Mar 12 #Python
You might like
深入php处理整数函数的详解
2013/06/09 PHP
php根据日期显示所在星座的方法
2015/07/13 PHP
9个比较实用的php代码片段
2016/03/15 PHP
yum命令安装php7和相关扩展
2016/07/04 PHP
laravel-admin解决表单select联动时,编辑默认没选上的问题
2019/09/30 PHP
javascript concat数组累加 示例
2009/09/03 Javascript
jquery选择器的选择使用及性能介绍
2013/01/16 Javascript
Javascript表格翻页效果实现思路及代码
2013/08/23 Javascript
jquery中子元素和后代元素的区别示例介绍
2014/04/02 Javascript
JavaScript通过字典进行字符串翻译转换的方法
2015/03/19 Javascript
node.js抓取并分析网页内容有无特殊内容的js文件
2015/11/17 Javascript
基于jQuery实现鼠标点击导航菜单水波动画效果附源码下载
2016/01/06 Javascript
jQuery unbind 删除绑定事件详解
2016/05/24 Javascript
Node.js与MySQL交互操作及其注意事项
2016/10/05 Javascript
angular双向绑定模拟探索
2016/12/26 Javascript
纯js仿淘宝京东商品放大镜功能
2017/03/02 Javascript
javascript实现圣旨卷轴展开效果(代码分享)
2017/03/23 Javascript
Vue实现美团app的影院推荐选座功能【推荐】
2018/08/29 Javascript
vue 2.8.2版本配置刚进入时候的默认页面方法
2018/09/21 Javascript
Nuxt.js之自动路由原理的实现方法
2018/11/21 Javascript
傻瓜式vuex语法糖kiss-vuex整理
2018/12/21 Javascript
改变layer confirm弹窗按钮的颜色方法
2019/09/12 Javascript
js实现贪吃蛇小游戏
2019/10/29 Javascript
vue页面更新patch的实现示例
2020/03/25 Javascript
详解Vite的新体验
2021/02/22 Javascript
[01:00:25]NB vs Secret 2018国际邀请赛小组赛BO1 B组加赛 8.19
2018/08/21 DOTA
python打开文件并获取文件相关属性的方法
2015/04/23 Python
Python基于QRCode实现生成二维码的方法【下载,安装,调用等】
2017/07/11 Python
Python OpenCV实现图片上输出中文
2018/01/22 Python
PYTHON EVAL的用法及注意事项解析
2019/09/06 Python
Python实现自动访问网页的例子
2020/02/21 Python
Python单元测试及unittest框架用法实例解析
2020/07/09 Python
Python使用itcaht库实现微信自动收发消息功能
2020/07/13 Python
Columbia美国官网:美国著名的户外服装品牌
2016/11/24 全球购物
行政部总经理岗位职责
2014/01/04 职场文书
一条 SQL 语句执行过程
2022/03/17 MySQL