优雅、清晰和务实都是python的核心价值观,如果想通过操作和处理一个序列(或其他的可迭代对象)来创建一个新的列表时可以使用列表解析(

List comprehensions)和生成表达式,通过这两个操作,我们可以看到这三个观点是如何在python中和谐统一起来的。

列表解析

在需要改变列表而不是需要新建某列表时,可以使用列表解析。列表解析表达式为:

[exprforiter_variniterable]

[exprforiter_variniterableifcond_expr]

第一种语法:首先迭代iterable里所有内容,每一次迭代,都把iterable里相应内容放到iter_var中,再在表达式中应用该iter_var的内容,最后用表达式的计算值生成一个列表。

第二种语法:加入了判断语句,只有满足条件的内容才把iterable里相应内容放到iter_var中,再在表达式中应用该iter_var的内容,最后用表达式的计算值生成一个列表。

举例如下:

1.>>>L=[(x+1,y+1)forxinrange(3)foryinrange(5)]2.>>>L3. [(1,1), (1,2), (1,3), (1,4), (1,5), (2,1), (2,2), (2,3), (2,4),

(2,5), (3,1), (3,2), (3,3), (3,4), (3,5)]

1.>>>N=[x+10forxinrange(10)ifx>5]2.>>>N3. [16,17,18,19]

1. newlist=[x+5forxinolderlistifx>10]

一个更复杂的例子:

1.>>>num=[jforiinrange(2,8)forjinrange(i*2,50, i)]2.>>>num3. [4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,6,4.9,12,15,18,21,24,27,30,33,36,39,42,45,48,8,12,16,20,24,28,32,36,40,5.44,48,10,15,20,25,30,35,40,45,12,18,24,30,36,42,48,14,21,28,35,42,49]6.

1.>>>words='The quick brown fox jumps over the lazy dog'.split()2.>>>words3. ['The','quick','brown','fox','jumps','over','the','lazy','dog']4.>>>stuff=[[w.upper(), w.lower(), len(w)]forwinwords]5.>>>foriinstuff:6. print i7.8.9. ['THE','the',3]10. ['QUICK','quick',5]11. ['BROWN','brown',5]12. ['FOX','fox',3]13. ['JUMPS','jumps',5]14. ['OVER','over',4]15. ['THE','the',3]16. ['LAZY','lazy',4]17. ['DOG','dog',3]

上述代码的map()实现:、

>>>stuff=map(lambdaw: [w.upper(), w.lower(), len(w)], words)>>>foriinstuff:

...printi

...

['THE','the',3]

['QUICK','quick',5]

['BROWN','brown',5]

['FOX','fox',3]

['JUMPS','jumps',5]

['OVER','over',4]

['THE','the',3]

['LAZY','lazy',4]

['DOG','dog',3]

生成器表达式、

生成器表达式是在python2.4中引入的,当序列过长, 而每次只需要获取一个元素时,应当考虑使用生成器表达式而不是列表解析。生成器表达式的语法和列表解析一样,只不过生成器表达式是被()括起来的,而不是[],如下:

(exprforiter_variniterable)

(exprforiter_variniterableifcond_expr)

例:

>>>L=(i+1foriinrange(10)ifi%2)>>>Lat0xb749a52c>>>>L1=[]>>>foriinL:

... L1.append(i)

...>>>L1

[2,4,6,8,10]

生成器表达式并不真正创建数字列表, 而是返回一个生成器,这个生成器在每次计算出一个条目后,把这个条目“产生”(yield)出来。 生成器表达式使用了“惰性计算”(lazy evaluation,也有翻译为“延迟求值”,我以为这种按需调用call by need的方式翻译为惰性更好一些),只有在检索时才被赋值(

evaluated),所以在列表比较长的情况下使用内存上更有效。A generator object in python is something like a lazy list. The elements are only evaluated as soon as you iterate over them.

一些说明:

1. 当需要只是执行一个循环的时候尽量使用循环而不是列表解析,这样更符合python提倡的直观性。

foriteminsequence:

process(item)

2. 当有内建的操作或者类型能够以更直接的方式实现的,不要使用列表解析。

例如复制一个列表时,使用:L1=list(L)即可,不必使用:

L1=[xforxinL]

3. 当序列过长, 而每次只需要获取一个元素时,使用生成器表达式。、