Python 列表推导式
列表推导式-最简形式
本节我们将介绍一个具有Python特色的知识,它就是list comprehensions,即列表推导式。为何会使用英文单词呢?因为在许多教材或图书中,对于列表推导式有多种称呼,如列表解析式或列表生成式,类似于水浒传中的宋江,有时被 称为及时雨、忠义黑三郎或呼宝义,但这三个名字都指的是宋江,所以我们只需知道它们都是指列表推导式即可。
首先,我们来看它的最简单形式。语法表达式如下图:
一个中括号表示列表,然后是一个表达式,接着是一个for循环。这个语法可能让人感到有些难以理解。
下面通过一个例子来解释。在一个中括号内,有一个表达式对i进行平方操作,后跟一个for循环。那么程序如何执行这行代码呢?为了更好地理解这条语句,我们先将其进行切割,分为两部分:for循环之前和之后。第一部分是表达式,第二部分是for循环。当我们运行时,首先执行for循环,依次遍历列表中的值,并将其赋值给i。这个列表可以是可迭代对象,如列表、元组、字符串或字典等。然后,我们继续执行第二部分,即对包含i的表达式进行求值,这里是对i进行平方操作。因此,这行代码等价于一个for循环,然后对表达式进行求值。如下图所示:
下面我们通过一个具体的例子来实际使用列表推导式。我们创建一个名为list_comprehensions的Python文件,并注释了最简形式。我们首先使用for循环来实现。我们需要先创建一个空列表val,然后将1到5的平方存储在这个空列表中。我们可以使用for循环来实现这一操作代码如下:
list_val = []
for i in range(1,6):
list_val.append(i**2)
print(list_val)
输出结果:
[1, 4, 9, 16, 25]
接下来,我们使用列表推导式的方式。首先是一个中括号,表示这是一个列表。在列表中,我们先写上for循环,对于i在range(1, 6)中,然后是一个表达式,对这里生成的i进行操作,即求其平方。为了演示效果,我们创建一个名为new_list的新列表,并输出结果以检查是否与之前相同。代码如下:
# 最简形式
list_val = []
for i in range(1,6):
list_val.append(i**2)
print(list_val)
new_list = [ i ** 2 for i in range(1,6)]
print(new_list)
输出结果:
[1, 4, 9, 16, 25]
[1, 4, 9, 16, 25]
与使用for循环相同。这意味着使用列表推导式可以用一行代码实现相当于使用for循环三行代码的效果,因此具有很强的Python特色,也可以称为Pythonic。
此外,在这个表达式中,你可以进行许多操作,我们这里只是使用了求平方的一种操作。比如,我们可以对包含字符串的列表进行操作。代码如下:
# 初始列表
word_list = ['I','love','Python']
# 使用列表推导式生成一个新列表,其中包含原列表中每个单词的大写形式
print([i.upper() for i in word_list])
# 使用列表推导式生成一个新列表,其中包含原列表中每个单词的首字母大写形式
print([i.title() for i in word_list])
所以说这个表达式这里,你可以根据实际情况自行来定义,这就是最简单的形式。
列表推导式-过滤条件形式
接下来,我们将探讨列表推导式的第二种形式,即包含过滤条件的形式。让我们先来看一下它的语法格式。如下图所示:
这个格式与我们之前介绍的基本形式基本相同,唯一的区别在于最后添加了一个if条件语句,即if判断条件。我们通过一个例子来解释这种形式:
为了理 解这段代码,我们先将其分解。我们首先执行for循环,从range中依次获取i的值,这是第一步。然后在第二步,对每个i进行if语句的判断,如果条件满足,则执行第三步,获取i的值。如果条件不满足,则忽略该值,这是一种过滤条件。这种形式的等价形式是使用for循环,然后在内部使用if条件判断。只有当条件满足时,才执行后面的表达式。
接下来,我们通过一个具体的例子学习如何使用包含过滤条件的方式。我们先用for循环来实现,代码如下:
# 使用for循环将0到20之间的偶数放入一个列表中
list_value = [] # 创建一个空列表
for i in range(21):
if i % 2 == 0: # 判断是否为偶数
list_value.append(i) # 如果是偶数,则将其追加到列表中
print(list_value) # 输出结果
输出结果:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
现在,让我们使用列表推导式来实现相同的功能:
# 使用列表推导式将0到20之间的偶数放入一个列表中
list_value = [i for i in range(21) if i % 2 == 0]
print(list_value) # 输出结果
输出结果:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
这段代码的输出结果同样是包含0到20之间所有偶数的列表,但是只需一行代码即可完成,相比使用for循环更加简洁和Pythonic。
需要注意的是,在列表推导式中,我们可以使用if else语句进行条件判断。下面,我们将演示如何在for循环中使用if else,并利用列表推导式实现相同的功能。让我们先注释掉之前的例子,然后给出一个新的例子:
# 现在有一个包含三个名字的列表
names = ["AndyFeng", "JackMa", "Bill Gates"]
# 使用for循环和if else语句对列表进行处理
list_value = []
for i in names:
if len(i) < 8:
list_value.append(i.lower()) # 如果长度小于8,则转换为小写
else:
list_value.append(i.upper()) # 如果长度大于等于8,则转换为大写
print(list_value) # 输出结果
输出结果:
['ANDYFENG', 'jackma', 'BILL GATES']
接下来,我们使用列表推导式来实现相同的功能:
# 使用列表推导式和if else语句对列表进行处理
# 现在有一个包含三个名字的列表
names = ["AndyFeng", "JackMa", "Bill Gates"]
list_value = [i.lower() if len(i) < 8 else i.upper() for i in names]
print(list_value) # 输出结果
输出结果:
['ANDYFENG', 'jackma', 'BILL GATES']
这段代码的输出结果同样是根据名字长度进行转换后的结果,但是只需一行代码即可完成,更加简洁明了。需要注意的是,在列表推导式中,if else语句应该在for循环前面使用,而不是在后面。
列表推导式-循环嵌套形式
现在我们将探讨最后一种形式,即循环嵌套的形式。如下图所示:
在这个语法格式中,包含两个for循环。第一个for循环遍历list1中的元素,而第二个for循环则在第一个循环的基础上遍历list2中的元素。在两个循环执行完毕后,再执行后面的表达式。这段代码的功能相当于使用for循环嵌套。如下图所示:
接下来,我们通过一个例子来介绍这种循环嵌套的形式。代码如下:
# for循环嵌套
# 循环嵌套通常是对两个集合进行组合
# 使用for循环嵌套来组合“高富帅”和“白富美”
# 遍历“高富帅”和“白富美”,将它们相互组合,并将结果存入列表中
list_value = []
for i in "高富帅":
for j in "白富美":
list_value.append(i + j)
print(list_value)
输出结果:
['高白', '高富', '高美', '富白', '富富', '富美', '帅白', '帅富', '帅美']
分析一下这段代码,我们首先使用外层循环(for循环)获取到第一个字符串“高”,然后程序继续执行内层循环,在这里遍历第二个字符串“白”,然后将它们相互组合形成“高白”等字符串。内层循环结束后,再执行外层循环,将第一个字符串改为“富”,然后再次执行内层循环。最终,输出了各种组合的结果。
接下来,我们使用列表推导式来实现相同的功能。我们仍然使用两个for循环,第一个循环遍历“高富帅”,第二个循环遍历“白富美”,然后编写前面的表达式将它们相连,并将结果存入一个新的列表中。
# 使用列表推导式实现循环嵌套
# 通过两个for循环遍历“高富帅”和“白富美”,将它们相互组合并存入列表中
new_list = [i + j for i in "高富帅" for j in "白富美"]
print(new_list)
输出结果:
['高白', '高富', '高美', '富白', '富富', '富美', '帅白', '帅富', '帅美']
这次,我们介绍了列表推导式的几种形式。可以发现,使用列表推导式能够以非常简洁的方式创建列表,即便是需要几行代码才能实现的问题,使用列表推导式只需一行代码即可完成。另外,它还具有更高的效率,因为在执行时调用的是Python底层的c代码,而不是使用Python代码。然而,不应滥用列表推导式,特别是在涉及复杂业务逻辑时。因为过度使用会导致代码难以理解。因此,在这种情况下,最好使用传统的for循环,以提高代码的可读性。