一、介绍
列表推导(list comprehensions)
这是一种将for循环、if表达式以及赋值语句放到单一语句中的一种方法。换句话说,你能够通过一个表达式对一个列表做映射或过滤操作。
一个列表推导式包含以下几个部分:
1、一个输入序列
2、一个表示输入序列成员的变量
3、一个可选的断言表达式
4、一个将输入序列中满足断言表达式的成员变换成输出列表成员的输出表达式
二、举例
假如需要从列表中将所有大于0的整数平方生成一个新的列表,你也许会这么写:
num_list = [11,2,-33,10,7,3,5,43]
squared_list = []
for num in num_list:
if num > 0:
squared_list.append(num**2)
print squared_list
# [121, 4, 100, 49, 9, 25, 1849]
很简单是吧?但是这就会有4行代码,两层嵌套外加一个完全不必要的append操作。而如果使用filter、lambda和map函数,则能够将代码大大简化:
num_list = [11,2,-33,10,7,3,5,43]
squared_list = map(lambda x: x ** 2,filter(lambda x:x>0,num_list))
print squared_list
# [121, 4, 100, 49, 9, 25, 1849]
下面使用列表推导
num_list = [11,2,-33,10,7,3,5,43]
squared_list = [x**2 for x in num_list if x >0]
print squared_list
# [121, 4, 100, 49, 9, 25, 1849]
三、说明
1、迭代器(iterator)遍历输入序列num的每个成员x
2、断言式判断每个成员是否大于零
3、如果成员大于零,则被交给输出表达式,平方之后成为输出列表的成员。
列表推导式被封装在一个列表中,所以很明显它能够立即生成一个新列表。这里只有一个type函数调用而没有隐式调用lambda函数,列表推导式正是使用了一个常规的迭代器、一个表达式和一个if表达式来控制可选的参数。
另一方面,列表推导也可能会有一些负面效应,那就是整个列表必须一次性加载于内存之中,这对上面举的例子而言不是问题,甚至扩大若干倍之后也都不是问题。但是总会达到极限,内存总会被用完。
针对上面的问题,生成器(Generator)能够很好的解决。生成器表达式不会一次将整个列表加载到内存之中,而是生成一个生成器对象(Generator objector),所以一次只加载一个列表元素。
生成器表达式同列表推导式有着几乎相同的语法结构,区别在于生成器表达式是被圆括号包围,而不是方括号,除非特殊的原因,应该经常在代码中使用生成器表达式。但除非是面对非常大的列表,否则是不会看出明显区别的。
num_list = [11,2,-33,10,7,3,5,43]
squared_list= list(x**2 for x in num_list if x >0)
print squared_list
# [121, 4, 100, 49, 9, 25, 1849]
这比列表推导效率稍微提高一些,让我们再一次改造一下代码:
num_list = [11,2,-33,10,7,3,5,43]
def square_generator(p):
return list(x ** 2 for x in num_list if x > p) print square_generator(0)
# [121, 4, 100, 49, 9, 25, 1849]
print square_generator(10)
# [121, 1849]