Logo
Section 1 / 14

列表推导式

学习如何使用列表推导式让代码更易读且更简洁。

导入

列表推导式

学习如何使用列表推导式让代码更易读且更简洁。

简介

列表(list)是 Python 标准库提供的几种 容器序列 之一,它存储的是其所包含对象的 引用。列表是一种 可变序列。

✏️ 注意:若需复习列表的基本概念,请先回顾创建列表的基础知识。

假设你已掌握列表的基础知识,接下来我们将深入探讨列表推导式——一种使用频率不高但功能强大且简洁的创建列表的方法。

列表推导式由方括号组成,其中包含一个 表达式,后接一个 for 子句,然后可以跟零个或多个 for 或 if 子句。结果是一个新列表,该列表由在后续 for 和 if 子句的上下文中评估表达式而生成。

...
列表推导式

说明

提升代码可读性

让我们看看列表推导式如何让程序更加清晰简洁。以下是不使用列表推导式实现列表的示例代码:

1letters = 'Python' 2alphabets = [] # 创建一个新列表 3 4for letter in letters: 5 alphabets.append(letter) # 将 letters 中的元素添加到 alphabets 6 7print(alphabets)

在上述代码中,我们在第 2 行创建了一个空列表 alphabets,然后在第 5 行通过 for 循环用 letters 列表填充它。现在,我们改用列表推导式实现相同功能,观察代码量如何减少,程序也变得更易读。

1letters = 'Python' 2alphabets = [letter for letter in letters] # 将 letters 中的元素添加到 alphabets 3 4print(alphabets)

现在你看到了,列表推导式多么高效!我们仅用一行代码就完成了 alphabets 的创建和填充,而之前没有使用推导式的版本则需要三行才能完成同样的任务。后者看起来更像是由 Python 专家编写的代码。

Python 3 中无变量泄漏问题

如果你曾使用过 Python 2,可能会注意到,在使用列表推导式时,变量会因 外部作用域 而导致值被意外覆盖。运行以下代码观察这一问题:

1letters = 'Python' 2alphabets = [letters for letters in letters] # letters 的作用域为外部作用域 3 4print(letters)

你会发现,当打印 letters(第 4 行)时,输出不再是 Python,而是 n。这是因为 Python 2 的列表推导式不会创建新的作用域,循环变量 letters 会覆盖第 1 行定义的同名变量,循环结束后 letters 的值变成了最后一个元素 n。

Python 3 解决了这个问题。它将 letters for letters in letters 中第一个 letters 的作用域改为 局部作用域,而非外部作用域。运行以下代码,见证这一改进!

1letters = 'Python' 2alphabets = [letters for letters in letters] # letters 的作用域为局部作用域 3 4print(letters)

Python 3 成功保留了 letters 的原始值。此时,letters for letters in letters 中第一个 letters 的作用域是 局部作用域,不再指向第 1 行定义的 letters。

使用列表推导式进行过滤

我们可以使用 for 循环或 filter 函数从列表中筛选数据,但这通常需要多行代码。你是否希望用一行代码完成?如果愿意,那就使用列表推导式。

运行以下代码,看看列表推导式如何实现列表过滤:

1numbers = [1,2,3,4,5,6,7,8,9,10] 2even = [number for number in numbers if number %2 ==0] # 筛选偶数 3 4print(even)

看,列表推导式效果惊人!它使用 for 关键字从 numbers 中逐个取出数字,并通过 if 条件进行筛选,所有操作都在一行代码中完成。

用列表推导式实现复杂迭代

列表推导式还能替代嵌套的 for 循环,提升效率。下面我们对比两种写法。以下是不使用列表推导式实现复杂迭代的代码:

1even = [2,4,6,8,10] 2odd = [1,3,5,7,9] 3 4pair = [] 5for number1 in even: # 从 even 中逐个取数 6 for number2 in odd: # 从 odd 中逐个取数 7 pair.append((number1, number2)) # 将 even 中的每个数与 odd 中的每个数配对 8 9print(pair)

在上述代码中,外层循环(第 5 行)逐个从 even 中取值,内层循环(第 6 行)逐个从 odd 中取值,然后将这些数以元组形式添加到 pair 列表中。最终,pair 包含了 even 和 odd 两个列表的 笛卡尔积。

❌ 注意:不应使用来自同一列表的元素生成元组对!

现在,我们改用列表推导式实现相同功能,观察代码如何大幅缩减,同时更易读:

1even = [2,4,6,8,10] 2odd = [1,3,5,7,9] 3 4# 将 even 中的每个数与 odd 中的每个数配对 5pair = [(number1,number2) for number1 in even for number2 in odd] 6 7print(pair)

再次证明,列表推导式非常高效!我们仅用一行代码(第 5 行)就完成了 pair 的创建和填充,而之前没有使用推导式的版本需要四行代码才能完成。后者的写法明显更具专业感。

掌握这些编程技巧,将显著提升你的代码质量与效率。

简介

元组