1.7 从另一个列表创建列表——列表推导
推导是从一个序列创建另一个序列的操作,例如,我们可以从列表或元组中创建一个列表。本节我们将讲述列表推导。一般地,列表推导具有以下特点。
序列,表示一个我们对其元素感兴趣的列表。
序列的元素拥有可变的表示方法。
使用输入序列的元素来产生输出表达式,以此产生输出序列。
一个可选的谓词表达式。
1.7.1 准备工作
我们先通过一个Python的脚本示例来理解列表推导中涉及的元素的不同之处。先输入一个列表,元素包含了一些正数和负数,我们希望得到的输出是由那些负数元素的平方值构成的列表。
1.7.2 操作方法
下面的示例代码演示了列表推导操作。
# 1.定义一个由一些正整数和负整数构成的简单列表
a = [1,2,-1,-2,3,4,-3,-4]
# 2.现在让我们写出列表推导
# pow()是幂函数,需要两个输入参数,第1个参数是底数,第2个参数是指数,返回的输出为幂值
b = [pow(x,2) for x in a if x < 0]
# 3.最后我们看看保存在新建的列表b里的输出结果
print b
1.7.3 工作原理
这个示例解释了列表推导的不同组成部分。我们来看第2步。
b = [pow(x,2) for x in a if x < 0]
这行代码可做如下解释。
输入是列表a,输出为列表b。
我们用变量x来表示列表中的每个元素。
pow(x,2)是输出表达式,使用输入列表中的元素来计算产生输出列表。
最后,“if x < 0”是一个谓词表达式,它负责选择输入列表中的哪些元素来计算产生输出列表。
1.7.4 更多内容
对字典来说,推导的语法也是相同的,我们来看一个简单的示例。
a = {'a':1,'b':2,'c':3}
b = {x:pow(y,2) for x,y in a.items()}
print b
在上面的示例中,我们从输入的字典a中创建了一个新的字典b,输出结果如下。
{'a': 1, 'c': 9, 'b': 4}
我们保留了字典的键,但其新值是字典a中原来的值的平方。值得注意的一点是在推导过程中,花括号代替了括号。
我们也可以采用一点小技巧来给元组做推导,请看下面的示例。
def process(x):
if isinstance(x,str):
return x.lower()
elif isinstance(x,int):
return x*x
else:
return -9
a = (1,2,-1,-2,'D',3,4,-3,'A')
b = tuple(process(x) for x in a )
print b
我们编写了一个新的处理函数来替代pow()函数,我把它留给读者作为一个练习,以理解这个处理函数的作用。请注意我们遵循和推导列表一样的语法。不过,我们使用圆括号代替括号,这段代码的输出会返回如下错误信息。
<generator object <genexpr> at 0x05E87D00>
哎,我们想要一个元组,但是被一个迭代器终结了(后面的章节我们会介绍迭代器),正确的方式应该是下面这样的。
b = tuple(process(x) for x in a )
这样,“print b”语句将产生如下输出。
(1, 4, 1, 4, 'd', 9, 16, 9, 'a')
Python的推导是基于集迭代器符号的,请参见:
http://en.wikipedia.org/wiki/Set-builder_notation。
关于Itertools.dropwhile,请参见:
https://docs.python.org/2/library/itertools.html#itertools.dropwhile。
借助谓词和序列,dropwhile将只返回满足那些谓词表达式的序列中的项。