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

Python “列表理解”是什么意思?它是如何工作的,我如何使用它?,python,list,list-comprehension,Python,List,List Comprehension,我有以下代码: [x ** 2 for x in range(10)] 当我在Python shell中运行它时,它返回: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 我已经搜索过了,这似乎被称为列表理解,但它是如何工作的呢 列表理解提供了创建列表的简明方法。常见的应用程序是创建新的列表,其中每个元素是应用于另一个序列或iterable的每个成员的某些操作的结果,或者创建满足特定条件的这些元素的子序列 关于您的问题,列表理解与以下普通Python代码的作用相同:

我有以下代码:

[x ** 2 for x in range(10)]
当我在Python shell中运行它时,它返回:

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
我已经搜索过了,这似乎被称为列表理解,但它是如何工作的呢

列表理解提供了创建列表的简明方法。常见的应用程序是创建新的列表,其中每个元素是应用于另一个序列或iterable的每个成员的某些操作的结果,或者创建满足特定条件的这些元素的子序列

关于您的问题,列表理解与以下普通Python代码的作用相同:

>>> l = [] 
>>> for x in range(10):
...     l.append(x**2)
>>> l
[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作为另一个函数的参数:

>>> [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。例如,您只需要范围为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。。。其他的在x之后,而不是在范围10之后:

你听说了吗?您可以在一个列表中放置两个或多个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]
>>> {i: i**2 for i in range(5)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
让我们来讨论第一部分,对于[1,2,3],[4,5,6]]中的x,它给出了[1,2,3]和[4,5,6]。然后,对于x中的i,给出1,2,3和4,5,6

警告:您始终需要在[1,2,3]、[4,5,6]]中输入x,然后再输入x中的i:

这与:

>>> set([i for i in [1, 1, 2, 3, 3, 1]])
{1, 2, 3}
>>> def gen():
...     for i in range(5):
...         yield i
>>> gen()
<generator object gen at 0x7f5270380db0>
A看起来像集合理解,但它使用{key:value for key,value in…}或{i:i for i in…}而不是{i for i in…}

例如:

>>> [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]
>>> {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}
我在5范围内是否给出了一个元组?不这是一个好主意。它返回一个生成器:

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

与生成器相关:。

有列表、字典和集合的理解,但没有元组的理解,尽管它们可以探索生成器表达式

它们解决了Python中的传统循环是语句不返回任何东西的问题,而不是返回值的表达式

它们不是所有问题的解决方案,可以重写为传统循环。当需要在迭代之间维护和更新状态时,它们会变得笨拙

它们通常包括:

[<output expr> <loop expr <input expr>> <optional predicate expr>]
但是可以用很多有趣和奇怪的方式扭曲

它们可以类似于Python中仍然存在并继续使用的传统映射和过滤操作


如果做得好,他们会有很高的满意度。

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

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

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

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

速成班 下面是集合生成器符号工作原理的基本知识:

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

混淆点 1集合生成器表示法中的谓词过滤器仅指定要保留的项,列表理解谓词也执行相同的操作。您不必包含省略项的特殊逻辑,除非谓词包含这些项,否则它们将被省略。空谓词(即末尾无条件)包括给定集合中的所有项

2集合生成器表示法中的谓词过滤器位于末尾,类似地,在列表理解中也是如此。一些初学者认为[x<5,范围10中的x]会给出列表[0,1,2,3,4],而实际上它会输出[True,True,True,True,True,False,False]。我们得到输出[真,真,真,真,真,真,假,假,假,假],因为我们要求Python为range10中的所有项计算x<5。无谓词意味着我们从集合中获取一切,就像在集合生成器符号中一样

如果您在使用列表理解时将set-builder符号放在脑后,那么它们会更容易接受

导言

列表理解是在Python中创建列表的一种高级声明方式。理解的主要好处是可读性和可维护性。很多人都喜欢 它们非常可读,甚至以前从未见过它们的开发人员通常也能正确地猜出它的意思

片段1 正方形=[n**2表示范围5中的n] 片段2 正方形=[] 对于范围5中的n: 正方形。附录**2 这两段代码都将生成等于[0,1,4,9,16]的正方形

请注意,在第一个代码段中,您键入的是声明您想要的列表类型,而第二个代码段指定如何创建它。这就是为什么理解是一种高层次的陈述式理解

语法

[序列中变量的表达式] 表达式是任何Python表达式,但其中通常包含一些变量。此变量在变量字段中说明。序列定义变量枚举通过的值的源

考虑到代码段1,[n**2表示范围5中的n]:

表达式为n**2 变量为n 顺序是5 请注意,如果您检查正方形的类型,您将得到列表理解只是一个常规列表:

>>> type(squares)
<class 'list'>
筛选:

最终列表中元素的顺序由顺序决定。但是,您可以通过添加if子句过滤掉元素:

[序列if条件中变量的表达式] 条件是计算结果为True或False的表达式。从技术上讲,条件不必依赖于变量,但它通常使用它

示例:

>>>[n**2表示范围5中的n,如果n%2==0] [0, 4, 16] >>>动物=[‘狗’、‘猫’、‘狮子’、‘老虎’] >>>[如果lenanimal==3,则动物对动物中的动物] [‘狗’、‘猫’] 另外,请记住Python允许您编写列表以外的其他类型的理解:

词典理解 集合理解
三元表达式x if cond else y实际上与列表理解没有任何特别的关系-任何有效的表达式都可以在列表压缩中使用-三元表达式是许多python表达式中的一个。@AChampion:是的,我在回答中提到了这一点,因为我尝试了[I for I in x if I else y]当我学习列表理解时,它不起作用。经过一些研究后,我明白我必须使用[I if y for I in x]。因此,我认为如果我在这里提到它,那么其他人可以避免我以前遇到的问题。值得一提的是,您只需要使用列表构造函数:Python 3中的列表。x@user3100115:是的,我在示例中使用了它。检查listmaplambda x:x**2,范围10-1。@minitoto:怎么了?这是列表理解的一个特点,称为嵌套列表理解。这让我很高兴:如果做得好,他们会有很高的满意度。
>>> 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(i**2 for i in range(5))
30
[<output expr> <loop expr <input expr>> <optional predicate expr>]
# 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)
>>> type(squares)
<class 'list'>