在Python中使用列表推导式List Comprehension的8个层次

在Python中使用列表推导式的8 个层次(8 Levels of Using List Comprehension in Python)

文章目录

  • [在Python中使用列表推导式的8 个层次(8 Levels of Using List Comprehension in Python)](#在Python中使用列表推导式的8 个层次(8 Levels of Using List Comprehension in Python))
    • [Level 0: 了解列表推导式List Comprehension的模板Template](#Level 0: 了解列表推导式List Comprehension的模板Template)
    • [Level 1: 只需替换 For 循环](#Level 1: 只需替换 For 循环)
    • [Level 2: 巧妙使用 If 条件Condition](#Level 2: 巧妙使用 If 条件Condition)
    • [Level 3: 使用更复杂的表达式More Complex Expression](#Level 3: 使用更复杂的表达式More Complex Expression)
    • [Level 4: 使用嵌套For循环处理嵌套Iterables](#Level 4: 使用嵌套For循环处理嵌套Iterables)
    • [Level 5: 避免使用高阶函数Higher Order Functions以提高可读性Readability](#Level 5: 避免使用高阶函数Higher Order Functions以提高可读性Readability)
    • [Level 6: 使用生成器表达式Generator Expressions降低内存开销Reduce Memory Costs](#Level 6: 使用生成器表达式Generator Expressions降低内存开销Reduce Memory Costs)
    • [Level 7: 了解列表推导式List Comprehension背后的哲学Philosophy](#Level 7: 了解列表推导式List Comprehension背后的哲学Philosophy)
    • 结论

列表表达式 list comprehension是一种非常具有 Pythonic 风格的技术,能让你的代码变得非常优雅。不过,它的语法有点令人困惑,尤其是对于新手和来自其他语言的程序员来说。我读过很多关于它的资料,但说实话,没有一本能完美地展示列表理解的全貌,以及它有多么强大和美丽。因此,我写了这篇文章。

本篇文章将由浅入深elementary to profound地展示使用列表表达式list comprehension的 8 个层次。在了解了所有 8 个层次之后,掌握列表表达式list comprehension就变得易如反掌了。

在Python中,"List comprehension"是指一种简洁的语法结构,用于快速创建新的列表,同时对列表中的元素进行处理和筛选。因此,我们可以将"List comprehension"理解为"列表理解"或"列表推导式"或"列表表达式",即通过理解和推导原始列表中的元素,生成一个新的列表。

Level 0: 了解列表推导式List Comprehension的模板Template

首先,我们应该了解基本语法:

每个列表推导式List Comprehension都应遵守以下模板:

python 复制代码
my_list = [ expression for item in iterable (if condition) ]

它非常简洁明了。只有两个方括号square brackets,包括三个关键组件components:

  • 迭代iterate可迭代对象iterable的 for 循环
  • 处理项item的表达式expression
  • 一个可选的 if 条件condition

接下来,让我们看看如何利用这个简单的模板编写巧妙的程序。

Level 1: 只需替换 For 循环

一个直观的方案是用一行代码替换 for 循环:

python 复制代码
full_name = "Zhang San"
characters = [char for char in full_name]
print(full_name)
print(characters)
# Zhang San
# ['Z', 'h', 'a', 'n', 'g', ' ', 'S', 'a', 'n']

与下面的 for 循环版本实现相比,这已经是向 Pythonic 和优雅程序迈进了一大步。

python 复制代码
full_name = "Zhang San"
characters = []
for char in full_name:
    characters.append(char)
print(full_name)
print(characters)
# Zhang San
# ['Z', 'h', 'a', 'n', 'g', ' ', 'S', 'a', 'n']

实际上,Python 中的所有可迭代对象iterables都可以在列表推导式List Comprehension中使用。再举一个例子

python 复制代码
Matrix = [[2, 1, 5],
          [5, 99, 0],
          [33, 2, 4]]
row_max = [max(row) for row in Matrix]
print(row_max)
# [5, 99, 33]

如上例所示,我们只需一行代码就能得到矩阵matrix中每一行的最大值maximum value。

Level 2: 巧妙使用 If 条件Condition

if 语句statement是列表推导式List Comprehension中的一个可选条件optional condition。如果使用得当,它会给我们带来很多方便。

python 复制代码
Genius = ["Yang", "Tom", "Jerry", "Jack", "tom", "yang"]
L1 = [name for name in Genius if name.startswith('Y')]
L2 = [name for name in Genius if name.startswith('Y') or len(name) < 4]
L3 = [name for name in Genius if len(name) < 4 and name.islower()]
print(L1, L2, L3)
# ['Yang'] ['Yang', 'Tom', 'tom'] ['tom']

Level 3: 使用更复杂的表达式More Complex Expression

在前面的示例中,我们只是获取项items来建立列表list。实际上,我们可以对 items 使用更复杂的表达式:

python 复制代码
Genius = ["Jerry", "Jack", "tom", "yang"]
L1 = [name.capitalize() for name in Genius]
print(L1)
# ['Jerry', 'Jack', 'Tom', 'Yang']

甚至包括 if...else... 语句:

python 复制代码
Genius = ["Jerry", "Jack", "tom", "yang"]
L1 = [name if name.startswith('y') else 'Not Genius' for name in Genius]
print(L1)
# ['Not Genius', 'Not Genius', 'Not Genius', 'yang']

注意:如果您没有真正理解列表推导式List Comprehension的模板Template,有一个问题可能会让您感到困惑:

表达式中的 if...else... 语句(也称为三元条件操作符ternary conditional operator)与列表推导式List Comprehension模板Template最后的可选 if 条件不同。让我们回顾一下模板:

python 复制代码
my_list = [ expression for item in iterable (if condition) ]

如模板所示,最后一个 if 条件是列表推导式List Comprehension的组成部分之一。我们不能在它后面添加 else 语句,因为列表推导式List Comprehension的语法不支持这样做。

只要遵循 Python 表达式的语法,表达式部分可以是任何表达式。如果我们使用 if ,则必须同时使用 else ,因为这是 Python 表达式的三元条件运算符ternary conditional operator语法。

python 复制代码
a = 1
b = 2 if a>0 # SyntaxError: invalid syntax

b = 2 if a > 0 else -1  
# b==2,ternary conditional operator works

Level 4: 使用嵌套For循环处理嵌套Iterables

一个列表推导式List Comprehension不仅可以替代一个 for-loop,实际上还可以替代嵌套的 for-loop。

python 复制代码
Genius = ["Jerry", "Jack", "tom", "yang"]
L1 = [char for name in Genius for char in name]
print(L1)
# ['J', 'e', 'r', 'r', 'y', 'J', 'a', 'c', 'k', 't', 'o', 'm', 'y', 'a', 'n', 'g']

上述程序等于

python 复制代码
Genius = ["Jerry", "Jack", "tom", "yang"]
L1 = []
for name in Genius:
    for char in name:
        L1.append(char)
print(L1)

哪种实现方式更好?答案显而易见。

当然,我们可以在一个列表推导式List Comprehension中放入更多嵌套的 for 循环,但这不是一个好主意。出于可读性的考虑,最好的做法best practice是在一个列表推导式List Comprehension中不要使用超过两个 for 循环。

此外,我们还可以在任何 for 循环之后添加可选的 if 条件conditions:

python 复制代码
Genius = ["Jerry", "Jack", "tom", "yang"]
L1 = [char for name in Genius if len(name) < 4 for char in name]
print(L1)
# ['t', 'o', 'm']

Level 5: 避免使用高阶函数Higher Order Functions以提高可读性Readability

Python 有一些高阶函数higher order functions,如 map()filter() 等。一个好的习惯是尽量使用列表推导式List Comprehension而不是使用高阶函数。因为它能让我们的程序更容易被他人阅读。甚至 Python 的作者也在他的文章中推荐了这种做法

map() 方法可以使用列表推导式List Comprehension进行替换:

python 复制代码
L = map(func, iterable)
# can be replaced to:
L = [func(a) for a in iterable]

filter() 方法也可以使用列表推导式List Comprehension进行转换:

python 复制代码
L = filter(condition_func, iterable)
# can be converted to
L = [a for a in iterable if condition]

让我们来看一个例子,下面的列表( L1L2 )用两种不同的方法实现,结果是一样的:

python 复制代码
Genius = ["Jerry", "Jack", "tom", "yang"]
L1 = filter(lambda a: len(a) < 4, Genius)
print(list(L1))
# ['tom']
L2 = [a for a in Genius if len(a) < 4]
print(L2)
# ['tom']

Level 6: 使用生成器表达式Generator Expressions降低内存开销Reduce Memory Costs

如果我们将方括号square brackets转换成括号parentheses,列表推导式List Comprehension就会变成一个生成器表达式generator expression。

生成器表达式generator expression可以避免生成一个完整的列表full list,从而降低内存成本reduce memory costs,因为生成器generator采用了 惰性求值lazy evaluation。

python 复制代码
large_list = [x for x in range(1_000_000)]
large_list_g = (x for x in range(1_000_000))
print(large_list.__sizeof__())
print(large_list_g.__sizeof__())
# 8697440
# 96

在Python中,__sizeof__()是一个特殊方法,用于返回对象所占用的内存大小(单位为字节)。它可以用于任何Python对象,包括列表、元组、字典、集合、自定义对象等。

Level 7: 了解列表推导式List Comprehension背后的哲学Philosophy

使用列表推导式List Comprehension的直观原因是为了使我们的代码更加整洁和优雅neat and elegant。此外Furthermore,这也是函数式编程范式functional programming paradigm的良好实践practice。函数式编程的理念之一就是避免控制流avoiding control flows。列表推导式List Comprehension可以将程序员的注意力从控制流control flow转移到数据收集data collection本身。换句话说,从思考 for 循环如何工作到思考列表是什么,这是一种心理上的转变。it's a mentally shift from thinking of how a for-loop works to what the list is. 它可以帮助你更容易地思考整个程序的逻辑。

结论

列表推导式List Comprehension是展示 Python 程序如何优雅elegant的经典示例classic example。在熟悉了它的语法syntax和使用场景using scenarios后,你的 Python 编程技能programming skills将进入一个新的境界new realm。

相关推荐
basketball6161 小时前
Python torchvision.transforms 下常用图像处理方法
开发语言·图像处理·python
兔子蟹子1 小时前
Java集合框架解析
java·windows·python
宁酱醇1 小时前
各种各样的bug合集
开发语言·笔记·python·gitlab·bug
谷晓光1 小时前
Python 中 `r` 前缀:字符串处理的“防转义利器”
开发语言·python
姚毛毛1 小时前
Windows上,10分钟构建一个本地知识库
python·ai·rag
站大爷IP1 小时前
Python ZIP文件操作全解析:从基础压缩到高级技巧
python
纪元A梦2 小时前
华为OD机试真题——通过软盘拷贝文件(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
java·javascript·c++·python·华为od·go·华为od机试题
用户867132495742 小时前
97% 的 Python 项目可以使用 partial() 更简洁
python
灏瀚星空3 小时前
从单机工具到协同平台:开源交互式模拟环境的技术演进之路
经验分享·笔记·python·开源·oneapi
西柚小萌新3 小时前
【Python爬虫实战篇】--Selenium爬取Mysteel数据
开发语言·爬虫·python