列表推导是构建列表( list )的快捷方式,而生成器表达式则可以用来创建其他任何类型的序列。如果你的代码里并不经常使用它们,那么很可能你错过了许多写出可读性更好且更高效的代码的机会。
列表推导和可读性
先来个小测试,你觉得下面2种代码,哪个更容易读懂?
- 示例1
texta ='abcd' textb = [] for i in texta : textb.append(symbol) print textb #['a', 'b', 'c', 'd']
- 示例2
texta ='abcd' textb =[symbo1 for symbo1 in symbols] print textb #['a', 'b', 'c', 'd']
虽然说任何学过一点 Python 的人应该都能看懂示例1。但是我觉得如果学会了列表推导的话,示例2读起来更方便,因为这段代码的功能从字面上就能轻松地看出来。
for 循环可以胜任很多任务,遍历一个序列以求得总数或挑出某个特定的元素、用来计算总和或是平均数,还有其他任何你想做的事情。在示例1的代码里,它被用来新建一个列表。
另一方面,列表推导也可能被滥用。以前看到过有的Python代码用列表推导来重复获取一个函数的副作用。通常的原则是,只用列表推导来创建新的列表,并且尽量保持简短。如果列表推导的代码超过了2行,你可能就要考虑是不是得用for循环来写了。就跟写文章一样,并没有什么硬性规则,这个度得你自己把握
列表推导同 filter 和 map 的比较
ftlter 和 map 合起来能做的事情,列表推导也可以做,而且还不需要借助难以理解和阅读的 lambda 表达式
获取"abcd"中ASCII值大于98的,并转为ASCII值
texta ="abcd"
listb =[ord(i) for i in texta if ord(i) > 98]
print listb
#['c', 'd']
texta ="abcd"
listb =list(filter(lambda i: i>98, map(ord,texta)))
print listb
生成器表达式
虽然也可以用列表推导来初始化元组、数组或其他序列类型,但是生成器表达式是更好的选择。这是因为生成器表达式背后遵守了迭代器协议,可以逐个地产出元素,而不是先建立一个完整的列表,然后再把这个列表传递到某个构造函数里。前面那种方式显然能够节省内存。
生成器表达式的语法跟列表推导差不多,只不过把方括号换成圆括号而已
- 使用生成器表达式初始化元组和数组
texta ="abcd" listb =tuple(ord(i) for i in texta) print listb
import array texta ="abcd" listb =array.array("I",(ord(i) for i in texta)) print listb #array('I', [97, 98, 99, 100])
应用
有黑、白2种颜色,和S、M、L3种型号的的T恤,怎么获取所有搭配类型
colors = ["black","white"]
sizes = ["S","M","L"]
lista = [("%s %s" % (c,s)) for c in colors for s in sizes]
print lista
#['black S', 'black M', 'black L', 'white S', 'white M', 'white L']
太感谢了大大