使用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>
但
In [31]: [y.x() for y in f]
Hi!
Hi!
Hi!
Hi!
这似乎是违反直觉的。
问题:为什么第一个表达式没有像生成列表那样生成从生成器获得的值的元组?
更新:当我更加盯着这一点时,我意识到在第一种情况下可能发生的事情是Python只是构建一个包含生成器的元组而不是评估生成器,因为它在第二种情况。
因为生成列表理解的结果直接无法获得元组,这是真的吗? (我知道我可以做tuple([y.x() for y in f])
)。我没有用例,这纯粹是为了我的理解。
答案 0 :(得分:3)
有些人将元组视为只读列表,并且在某些情况下有效。但这不是元组的语义意图。列表旨在用于均匀元素的可变长度结构(具有共享类型的元素)。元组用于固定长度结构,其中每个索引位置包含特定类型的元素。
enumerate(lst)
就是一个例子。它返回一个可变长度的元组列表。每个元组都有两个元素,第一个元素总是一个整数,第二个元素来自lst
。
有了这样的理解,元组生成器有点荒谬。这可能就是原因。
修改强>
至于直接生成元组,你可以比你的例子做得更好一些。这也有效:
tuple(y.x() for y in f)
将生成器传递给tuple()
方法,该方法构造一个元组,但不创建中间list
。
要明确指出,tuple
中没有(y.x() for y in f)
,但t = 1, 2, 3
中有一个元组。这不是构成元组的parens。这是逗号。
答案 1 :(得分:0)
问题:为什么第一个表达式没有生成元组的元组 以生成列表的方式从生成器获取的值?
这不是设计目的
见PEP-289
Tutorial始终是寻找答案的好地方
Generator Expressions
Expression lists - 描述了使用逗号来定义元组
因此不可能直接获得元组作为 生成列表理解的结果?
不 - 不像列表理解,它是一个生成器。它旨在为每次迭代生成单独的元素。