“列表理解”及其类似概念是什么意思?它如何工作以及如何使用它?
- 2024-11-18 08:41:00
- admin 原创
- 17
问题描述:
我有以下代码:
[x ** 2 for x in range(10)]
当我在 Python shell 中运行它时,它返回:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
我搜索了一下,似乎这被称为列表推导,类似地,似乎还有集合/字典推导和生成器表达式。但它是如何工作的呢?
解决方案 1:
来自文档:
列表推导提供了一种创建列表的简洁方法。常见的应用是创建新列表,其中每个元素都是对另一个序列或可迭代对象的每个成员应用某些操作的结果,或者创建满足特定条件的元素的子序列。
关于您的问题,列表推导与以下“简单”的 Python 代码的作用相同:
>>> l = []
>>> for x in range(10):
... l.append(x**2)
>>> l
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
你怎么才能用一行写出来呢?嗯...我们可以...可能...map()
使用lambda
:
>>> list(map(lambda x: x**2, range(10)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
但仅使用列表推导不是更清晰、更简单吗?
>>> [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
基本上,我们可以用 做任何事情x
。不仅限于x**2
。例如,运行 的方法x
:
>>> [x.strip() for x in ('foo
', 'bar
', 'baz
')]
['foo', 'bar', 'baz']
或者用作x
另一个函数的参数:
>>> [int(x) for x in ('1', '2', '3')]
[1, 2, 3]
例如,我们还可以将其用作对象x
的键dict
。让我们看看:
>>> d = {'foo': '10', 'bar': '20', 'baz': '30'}
>>> [d[x] for x in ['foo', 'baz']]
['10', '30']
组合一下怎么样?
>>> d = {'foo': '10', 'bar': '20', 'baz': '30'}
>>> [int(d[x].rstrip('0')) for x in ['foo', 'baz']]
[1, 3]
等等。
您还可以在列表推导中使用if
或if...else
。例如,您只希望 中的奇数range(10)
。您可以这样做:
>>> l = []
>>> for x in range(10):
... if x%2:
... l.append(x)
>>> l
[1, 3, 5, 7, 9]
啊,太复杂了。那么下一个版本呢?
>>> [x for x in range(10) if x%2]
[1, 3, 5, 7, 9]
要使用if...else
三元表达式,需要将 放在if ... else ...
之后x
,而不是之后range(10)
:
>>> [i if i%2 != 0 else None for i in range(10)]
[None, 1, None, 3, None, 5, None, 7, None, 9]
你听说过嵌套列表推导式吗?你可以在一个列表推导式中放入两个或更多个for
列表。例如:
>>> [i for x in [[1, 2, 3], [4, 5, 6]] for i in x]
[1, 2, 3, 4, 5, 6]
>>> [j for x in [[[1, 2], [3]], [[4, 5], [6]]] for i in x for j in i]
[1, 2, 3, 4, 5, 6]
我们先讨论第一部分,for x in [[1, 2, 3], [4, 5, 6]]
它给出[1, 2, 3]
和[4, 5, 6]
。然后,for i in x
给出1
,2
,3
和4
,5
,6
。
警告:你总是需要for x in [[1, 2, 3], [4, 5, 6]]
在之前 for i in x
放置:
>>> [j for j in x for x in [[1, 2, 3], [4, 5, 6]]]
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'x' is not defined
我们还有集合理解、字典理解和生成器表达式。
集合推导和列表推导基本相同,但前者返回一个集合而不是一个列表:
>>> {x for x in [1, 1, 2, 3, 3, 1]}
{1, 2, 3}
它与以下内容相同:
>>> set([i for i in [1, 1, 2, 3, 3, 1]])
{1, 2, 3}
字典推导式 看起来像集合推导式,但是它使用{key: value for key, value in ...}
或{i: i for i in ...}
代替 {i for i in ...}
。
例如:
>>> {i: i**2 for i in range(5)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
它等于:
>>> d = {}
>>> for i in range(5):
... d[i] = i**2
>>> d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
(i for i in range(5))
给出一个元组吗?不!这是一个生成器表达式。它返回一个生成器:
>>> (i for i in range(5))
<generator object <genexpr> at 0x7f52703fbca8>
它与以下内容相同:
>>> def gen():
... for i in range(5):
... yield i
>>> gen()
<generator object gen at 0x7f5270380db0>
您可以将其用作生成器:
>>> gen = (i for i in range(5))
>>> next(gen)
0
>>> next(gen)
1
>>> list(gen)
[2, 3, 4]
>>> next(gen)
Traceback (most recent call last):
File "<input>", line 1, in <module>
StopIteration
注意:如果你在函数中使用列表推导,则不需要[]
该函数是否可以循环遍历生成器。例如sum()
:
>>> sum(i**2 for i in range(5))
30
相关(关于生成器):理解 Python 中的生成器。
解决方案 2:
有列表、字典和集合理解,但没有元组理解(尽管确实探索了“生成器表达式”)。
它们解决了 Python 中的传统循环是语句(不返回任何内容)而不是返回值的表达式的问题。
它们并不是解决所有问题的方案,可以重写为传统循环。当需要在迭代之间维护和更新状态时,它们会变得很尴尬。
它们通常包括:
[<output expr> <loop expr <input expr>> <optional predicate expr>]
但可以以很多有趣和奇异的方式扭曲。
它们可以类似于Python 中仍然存在并继续使用的传统map()
与操作。filter()
如果做得好,他们会有很高的满意度。
解决方案 3:
如果你更喜欢用更直观的方式来了解发生了什么,那么也许这会有所帮助:
# for the example in the question...
y = []
for x in range(10):
y += [x**2]
# is equivalent to...
y = [x**2 for x in range(10)]
# for a slightly more complex example, it is useful
# to visualize where the various x's end up...
a = [1,2,3,4]
b = [3,4,5,6]
c = []
for x in a:
if x in b:
c += [x]
# /
# ___________/
# / \n# / \n# / \n# / \n# / \nc = [x for x in a if x in b]
print(c)
...产生输出[3, 4]
解决方案 4:
最近我看到很多人对列表推导的工作原理感到困惑(在其他 SO 问题上以及同事那里)。一点点数学知识可以帮助你理解为什么语法是这样的,以及列表推导的真正含义。
语法
最好将列表推导视为集合/集合上的谓词,就像我们在数学中使用集合构建器符号一样。这种符号对我来说实际上感觉很自然,因为我拥有数学本科学位。但别忘了我,Guido van Rossum(Python 的发明者)拥有数学硕士学位,并且有数学背景。
集合构建器符号速成课程
以下是集合构建器符号的工作原理(非常基础):
因此,这个集合构造器符号表示严格为正数的一组数字(即[1,2,3,4,...]
)。
容易混淆的地方
1)集合构建器表示法中的谓词过滤器仅指定我们要保留哪些项,列表理解谓词做同样的事情。您不必包含省略项的特殊逻辑,除非谓词包含它们,否则它们将被省略。空谓词(即末尾没有条件)包括给定集合中的所有项。
2)集合构建器符号中的谓词过滤器位于末尾,列表推导式中也是如此。(一些)初学者认为类似的东西[x < 5 for x in range(10)]
会给他们列表[0,1,2,3,4]
,而实际上它输出的是[True, True, True, True, True, False, False, False, False, False]
。我们得到输出是因为我们要求 Python对中的所有项目[True, True, True, True, True, False, False, False, False, False]
进行评估。没有谓词意味着我们从集合中得到所有东西(就像在集合构建器符号中一样)。x < 5
`range(10)`
如果在使用列表推导时心里记住集合构建器符号,它们就会更容易被接受。
呼呼!
解决方案 5:
介绍
列表推导式是在 Python 中创建列表的一种高级声明式方法。列表推导式的主要优点是可读性和可维护性。很多人觉得列表推导式非常易读,甚至从未见过列表推导式的开发人员通常也能正确猜出它的含义。
# Snippet 1
squares = [n ** 2 for n in range(5)]
# Snippet 2
squares = []
for n in range(5):
squares.append(n ** 2)
这两段代码都会产生squares
等于的结果[0, 1, 4, 9, 16]
。
请注意,在第一个代码片段中,您输入的是声明所需的列表类型,而第二个代码片段则指定如何创建列表。这就是为什么理解是高级且声明性的。
句法
[EXPRESSION for VARIABLE in SEQUENCE]
EXPRESSION
是任意 Python 表达式,但其中通常包含一些变量。此变量在VARIABLE
字段中说明。SEQUENCE
定义变量枚举的值的来源。
考虑代码片段 1 [n ** 2 for n in range(5)]
:
EXPRESSION
是n ** 2
VARIABLE
是n
SEQUENCE
是range(5)
请注意,如果你检查类型,squares
你会发现列表推导只是一个常规列表:
>>> type(squares)
<class 'list'>
有关 EXPRESSION 的更多信息
表达式可以是任何能简化为一个值的东西:
算术表达式,例如
n ** 2 + 3 * n + 1
函数调用就像
f(n)
使用n
变量一样切片操作如下
s[::-1]
方法调用
bar.foo()
...
一些例子:
>>> [2 * x + 3 for x in range(5)]
[3, 5, 7, 9, 11]
>>> [abs(num) for num in range(-5, 5)]
[5, 4, 3, 2, 1, 0, 1, 2, 3, 4]
>>> animals = ['dog', 'cat', 'lion', 'tiger']
>>> [animal.upper() for animal in animals]
['DOG', 'CAT', 'LION', 'TIGER']
筛选:
最终列表中元素的顺序由 的顺序决定SEQUENCE
。但是,您可以通过添加子句来过滤掉元素if
:
[EXPRESSION for VARIABLE in SEQUENCE if CONDITION]
CONDITION
是一个计算结果为True
或 的表达式False
。从技术上讲,该条件不必依赖于VARIABLE
,但通常会使用它。
例子:
>>> [n ** 2 for n in range(5) if n % 2 == 0]
[0, 4, 16]
>>> animals = ['dog', 'cat', 'lion', 'tiger']
>>> [animal for animal in animals if len(animal) == 3]
['dog', 'cat']
另外,请记住,Python 允许您编写除了列表之外的其他类型的推导式:
字典推导
集合推导
解决方案 6:
对于那些寻找嵌套内联运算符的人来说:
[(i,j) for i in range(8) for j in range(8)]
这相当于itertools.product
:
from itertools import product
list(product(range(8), range(8)))
对于其他上下文,这相当于以下嵌套循环:
results = []
for i in range(8):
for j in range(8):
coord = (i, j)
results.append(coord)
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件