【问题标题】:outputs of different list comprehensions in python 3.xpython 3.x 中不同列表推导的输出
【发布时间】:2021-04-12 20:59:08
【问题描述】:

我正在研究 Python 中的列表理解,我很困惑为什么这两个代码会产生不同的输出。 代码:

print([(letter,num) for letter in 'abc' for num in range(2)])
print([((letter,num) for letter in 'abc') for num in range(2)])

输出:

[('a', 0), ('a', 1), ('a', 2), ('a', 3), ('b', 0), ('b', 1), ('b', 2), ('b', 3), ('c', 0), ('c', 1), ('c', 2), ('c', 3), ('d', 0), ('d', 1), ('d', 2), ('d', 3)]

[<generator object <listcomp>.<genexpr> at 0x000002919E020F20>, <generator object <listcomp>.<genexpr> at 0x000002919E148C10>, <generator object <listcomp>.<genexpr> at 0x000002919E1489E0>, <generator object <listcomp>.<genexpr> at 0x000002919E148C80>]

【问题讨论】:

  • 我认为从额外括号的位置可以明显看出,但第一个是嵌套列表推导,而第二个是列表推导中的生成器表达式。
  • 您是否期望括号执行某种类型的操作顺序?

标签: python python-3.x list generator list-comprehension


【解决方案1】:

第一个例子:

print([(letter,num) for letter in 'abc' for num in range(2)])

打印一个列表(因为外部的[] 括号),其中包含letternum 的所有元组(因为letter, num 周围的括号),letter 的每个值循环到@987654327 @ 和 num 的每个值循环遍历由 range(2) 返回的生成器的每个值(将是 01)。

由于 Python 将第一个 for 作为外部循环,因此您会看到 ('a', 0), ('a', 1), 等而不是 ('a', 0), ('b', 0), 等。

但是,当您在 for 表达式(如 (letter,num) for letter in 'abc')周围添加括号时,您将不再执行推导式中的循环,而是捕获生成器(准备开始生成它们的值,但实际上并没有将值生成到理解中)。

所以:

print([((letter,num) for letter in 'abc') for num in range(2)])

这里,((letter,num) for letter in 'abc') 只是一个生成器,一旦你开始请求它们就会产生值。

注意:因为num的值没有单独包含在生成器中,如果你对它们做一些事情,你可能会看到一个令人惊讶的结果:

x = [((letter,num) for letter in 'abc') for num in range(2)]
print(next(x[0]))
print(next(x[0]))
print(next(x[0]))
print(next(x[1]))
print(next(x[1]))
print(next(x[1]))

结果:

('a', 1)
('b', 1)
('c', 1)
('a', 1)
('b', 1)
('c', 1)

【讨论】:

  • 明白了!感谢您的解释。 @Grismar
【解决方案2】:

第一个列表推导相当于嵌套循环:

result = []
for num in range(2):
    for letter in 'abc':
        result.append((letter, num))
print(result)

嵌套循环的每次迭代都会产生结果列表的一个元素。

第二个相当于单循环:

result = []
for num in range(2):
    result.append((letter, num) for letter in 'abc')
print(result)

循环的每次迭代都会将生成器对象附加到结果列表中。

您可以使用嵌套列表推导式,但结果将是嵌套列表,而不是第一个版本中的平面列表。

print([list((letter,num) for letter in 'abc') for num in range(2)])
# output: [[('a', 0), ('b', 0), ('c', 0)], [('a', 1), ('b', 1), ('c', 1)]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-22
    • 1970-01-01
    • 2019-03-23
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-02
    相关资源
    最近更新 更多