2

玩弄 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]))。我没有用例,这纯粹是为了我的理解。

4

2 回答 2

3

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

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

有了这种理解,元组生成器就有点荒谬了。这大概就是为什么。

编辑:

至于直接生成元组,你可以做得比你的例子好一点。这也有效:

tuple(y.x() for y in f)

这会将生成器传递给该tuple()方法,该方法构造一个元组,但不创建一个中间list.

需要明确的是, 中没有tuple涉及(y.x() for y in f),但 中有一个元组t = 1, 2, 3。构成元组的不是括号。是逗号。

于 2013-10-09T21:21:54.960 回答
0

问题:为什么第一个表达式没有按照构建列表的方式生成从生成器获得的值的元组?

这不是设计的目的。
请参阅PEP-289
教程始终是开始寻找答案的好地方。
生成器表达式
表达式列表- 描述使用逗号定义元组

那么,作为生成列表推导的结果,不能直接获取元组是真的吗?

不 - 不像列表推导,它是一个生成器。它旨在为每次迭代产生单独的元素。

于 2013-10-10T13:37:16.157 回答