在Python中,列表理解与列表和元组有什么区别?

在Python中,列表理解与列表和元组有什么区别?,python,list-comprehension,Python,List Comprehension,在玩iPython时,我惊讶地发现,给定一个对象列表f,每个对象都支持某种方法x()(也就是说,打印出“Hi!”),表达式: (y.x() for y in f) 在语义上不等同于 [y.x() for y in f] 第一个(以元组作为输出)生成一个生成器表达式,除非我对其进行迭代,否则不会对其求值,而带有列表的表达式实际上会立即生成: In [30]: (y.x() for y in f) Out[30]: <generator object <genexpr> at

在玩iPython时,我惊讶地发现,给定一个对象列表
f
,每个对象都支持某种方法
x()
(也就是说,打印出
“Hi!”
),表达式:

(y.x() for y in f)
在语义上不等同于

[y.x() for y in f]
第一个(以元组作为输出)生成一个生成器表达式,除非我对其进行迭代,否则不会对其求值,而带有列表的表达式实际上会立即生成:

In [30]: (y.x() for y in f)
Out[30]: <generator object <genexpr> at 0x2d78d70>
这似乎有点违反直觉

问:为什么第一个表达式不以构建列表的方式生成从生成器获得的值的元组


更新:当我进一步关注这一点时,我意识到第一种情况下可能发生的事情是Python只是构建一个包含生成器的元组,而不是像第二种情况那样评估生成器


那么,不可能直接获得元组作为生成列表的结果,这是真的吗?(我知道我可以做
元组([y.x()表示f中的y])
)。我没有用例,这纯粹是为了我的理解。

有些人将元组视为只读列表,这在某些上下文中是有效的。但这不是元组的语义意图。列表用于同质元素(具有共享类型的元素)的可变长度结构。元组用于固定长度的结构,其中每个索引位置包含特定类型的元素

enumerate(lst)
就是一个例子。它返回元组的可变长度列表。每个元组正好有两个元素,第一个元素始终是整数,第二个元素来自
lst

基于这种理解,元组生成器有点荒谬。这可能就是原因

编辑:

至于直接生成元组,您可以比您的示例做得更好一些。这也适用于:

tuple(y.x() for y in f)
它将生成器传递给
tuple()
方法,该方法构造一个元组,但不创建中间的
列表

需要明确的是,在
(y.x()表示f中的y)
中没有
元组,但在
t=1、2、3
中有一个元组。元组不是由帕伦构成的。是逗号

问题:为什么第一个表达式不生成 以创建列表的方式从生成器获得的值

这不是设计的目的。

总是一个开始寻找答案的好地方。

-描述如何使用逗号定义元组

那么,不可能直接获得元组作为 生成列表的结果


不-不像列表理解,它是一个生成器。它旨在为每次迭代生成单个元素。

为什么是什么?你已经知道了它的含义,即使它不是你最初期望的。您是否在问为什么存在生成器表达式?或者你在问为什么这个语法不生成元组(类似于列表理解)?或者别的什么?你是在问为什么它是反直觉的,或者为什么GeneX存在?如果它是反直觉的,那意味着你期望其他行为。你期望的是什么?元组构造函数是一个逗号,是思考它的最佳方式。顺便说一句,你期望的元组很可能源于一种误解,这种误解在其他上下文中也会咬你一口:假设parens表示元组。他们没有。创建元组的是逗号。
tuple(y.x() for y in f)