python,“列表理解”是什么意思?它是如何工作的,我如何使用它?

o2g1uqev  于 2021-07-13  发布在  Java
关注(0)|答案(5)|浏览(340)

我有以下代码:

[x**2 for x in range(10)]

当我在python shell中运行它时,它返回:

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

我已经搜索过了,似乎这就是所谓的列表理解,但它是如何工作的呢?

uurv41yg

uurv41yg1#

根据文件:
列表理解提供了一种创建列表的简洁方法。常见的应用程序是创建新的列表,其中每个元素是应用于另一个序列或iterable的每个成员的某些操作的结果,或者创建满足特定条件的这些元素的子序列。
关于您的问题,列表理解与以下“普通”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\n', 'bar\n', 'baz\n')]
['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

我们还有集合理解、dict理解和生成器表达式。
集合理解和列表理解基本相同,但前者返回集合而不是列表:

>>> {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中的生成器。

093gszye

093gszye2#

有list、dictionary和set理解,但没有元组理解(尽管您需要探索“生成器表达式”)。
它们解决了python中的传统循环是语句(不返回任何内容)而不是返回值的表达式的问题。
它们不是所有问题的解决方案,可以重写为传统的循环。当需要在迭代之间维护和更新状态时,它们会变得笨拙。
它们通常包括:

[<output expr> <loop expr <input expr>> <optional predicate expr>]

但是可以以许多有趣和奇怪的方式扭曲。
它们可以类似于传统的 map() 以及 filter() 仍然存在于python中并继续使用的操作。
如果做得好,他们会有很高的满意度。

htzpubme

htzpubme3#

我最近(在其他so问题和同事的问题上)看到很多关于列表理解如何工作的困惑。一点点的数学教育可以帮助理解为什么语法是这样的,以及列表理解的真正含义。

语法

最好将列表理解看作集合/集合上的 predicate ,就像我们在数学中使用集合生成器表示法一样。这个符号对我来说真的很自然,因为我拥有数学学士学位。但是忘了我吧,guido van rossum(python的发明者)拥有数学硕士学位,有数学背景。

设置速成课程

以下是集合生成器表示法的工作原理(非常基础):

因此,这个集合生成器符号表示严格正的一组数字(即。 [1,2,3,4,...] ).

混淆点

1) 集合生成器表示法中的 predicate 过滤器只指定要保留的项,列表理解 predicate 也做同样的事情。不必包含省略项的特殊逻辑,除非 predicate 包含它们,否则它们将被省略。空 predicate (即结尾没有条件)包含给定集合中的所有项。
2) 集合生成器表示法中的 predicate 过滤器位于末尾,在列表理解中也是如此(一些)初学者认为 [x < 5 for x in range(10)] 会给他们名单的 [0,1,2,3,4] ,而实际上它输出 [True, True, True, True, True, False, False, False, False, False] . 我们得到了结果 [True, True, True, True, True, False, False, False, False, False] 因为我们让python评估 x < 5 对于中的所有项目 range(10) . no predicate 意味着我们从集合中获取所有内容(就像在集合生成器符号中一样)。
如果您在使用列表理解时将set-builder符号放在脑后,它们就更容易接受了。
嗯!

wz1wpwve

wz1wpwve4#

如果你更喜欢用一种更直观的方式来了解发生了什么,那么这也许会有所帮助:


# 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]

# \         \        /

# \    _____\______/

# \  /      \

# \/        \

# /\         \

# /  \         \

# /    \         \

c = [x for x in a if x in b]

print(c)

…产生输出 [3, 4]

nnvyjq4y

nnvyjq4y5#

介绍
列表理解是在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'>

有关表达式的详细信息
表达式可以是任何减少到某个值的内容:
算术表达式,例如 `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允许您编写除列表以外的其他类型的理解:
词典理解
集合理解

相关问题