在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。

相关推荐
The Future is mine38 分钟前
Python计算经纬度两点之间距离
开发语言·python
九月镇灵将40 分钟前
GitPython库快速应用入门
git·python·gitpython
兔子的洋葱圈1 小时前
【django】1-2 django项目的请求处理流程(详细)
后端·python·django
独好紫罗兰1 小时前
洛谷题单3-P5719 【深基4.例3】分类平均-python-流程图重构
开发语言·python·算法
27669582921 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
橘子在努力2 小时前
【橘子大模型】关于PromptTemplate
python·ai·llama
SheepMeMe2 小时前
蓝桥杯2024省赛PythonB组——日期问题
python·算法·蓝桥杯
莓事哒2 小时前
selenium和pytessarct提取古诗文网的验证码(python爬虫)
爬虫·python·selenium·测试工具·pycharm
q567315233 小时前
使用puppeteer库编写的爬虫程序
爬虫·python·网络协议·http
mosquito_lover13 小时前
Python数据分析与可视化实战
python·数据挖掘·数据分析