这个语句的核心是 for 循环, 它迭代 iterable 对象的所有条目. 前边的 expr 应用于序列的每个成员, 最后的结果值是该表达式产生的列表。 迭代变量并不需要是表达式的一部分。例如用 lambda 函数计算序列成员的平方的表达是为:
map(lambda x: x ** 2, range(6))这可以用列表解析来改写:
[x ** 2 for x in range(6)]列表解析的表达式可以取代内建的 map() 函数以及 lambda , 而且效率更高。结合 if 语句,列表解析还提供了一个扩展版本的语法:
[expr for iter_var in iterable if cond_expr]这个语法在迭代时会过滤/捕获满足条件表达式 cond_expr 的序列成员。例如挑选出序列中的奇数可以用下边的方法:
[x for x in seq if x % 2]列表解析还有很多巧妙的应用:
迭代一个有三行五列的矩阵:
[(x+1,y+1) for x in range(3) for y in range(5)]计算出所有非空白字符的数目:
f = open('hhga.txt', 'r')len([word for line in f for word in line.split()])
生成器表达式是列表解析的一个扩展。列表解析的一个不足就是必要生成所有的数据, 用以创建整个列表。这可能对有大量数据的迭代器有负面效应。生成器表达式通过结合列表解析和生成器解决了这个问题。生成器表达式在 Python 2.4 被引入, 它与列表解析非常相似,而且它们的基本语法基本相同; 不过它并不真正创建数字列表, 而是返回一个生成器,这个生成器在每次计算出一个条目后,把这个条目“产生”(yield)出来。生成器表达式使用了"延迟计算"(lazy evaluation), 所以它在使用内存上更有效。生成器表达式语法:
(expr for iter_var in iterable if cond_expr)生成器并不会让列表解析废弃, 它只是一个内存使用更友好的结构, 基于此, 有很多使用生 成器地方,如下所示:
快速地计算文件大小:
上面我们用列表解析计算出了文件中非空白字符的数目,那么只要用 sum() 函数对每个单词的长度求和,则可大致计算出文件的大小。sum() 函数的参数不仅可以是列表,还可以是可迭代对象,比如生成器表达式。这里我们用生成器表达式改写整个过程:
sum(len(word) for line in data for word in line.split())交叉配对:
生成器表达式就好像是懒惰的列表解析(这反而成了它主要的优势)。它还可以用来处理其他列表或生成器:
rows = [1, 2, 3, 17] def cols(): # example of simple generator yield 56 yield 2 yield 1 x_product_pairs = ((i, j) for i in rows for j in cols()) for pair in x_product_pairs: print pair
寻找文件最长的行:
def longest(filename): glines = (x.strip() for x in open(filename)) return max([len(l) for l in glines]) # Script starts from here if __name__ == "__main__": print longest("/etc/hosts")
这个例子摘自 《Python核心编程》 中生成器表达式一节,作者在原书中只用了一行代码来实现这个功能,即:
return max(len(x.strip()) for x in open('/etc/motd'))这行代码会报出如下错误:
TypeError: object of type 'generator' has no len()
也就是说生成器没有 len() 方法,所以这样并不可行,但是用列表解析则可以用一行实现:
return max([len(x.strip()) for x in open("/etc/motd")])