In Python, whats the difference between a list comprehension with a list and a tuple?

大城市里の小女人 提交于 2021-01-27 20:15:50

问题


Playing around with iPython, I was surprised to discover that given a list f of objects each supporting some method x() (that, say, prints out "Hi!"), the expression:

(y.x() for y in f)

is not semantically equivalent to

[y.x() for y in f]

The first one (with the tuple as output) results in a generator expression that is not evaluated unless I iterate over it, whereas the one with the list actually causes the generation to happen immediately:

In [30]: (y.x() for y in f)
Out[30]: <generator object <genexpr> at 0x2d78d70>

but

In [31]: [y.x() for y in f]
Hi!
Hi!
Hi!
Hi!

This seems rather counter-intuitive.

Question: Why is the first expression not generating a tuple of the values obtained from the generator the way the list is being built?


Update: As I stare at this more, I realize that perhaps what's happening in the first case is that Python is just building a tuple containing a generator rather than evaluating the generator as it is in the second case.

So is it true that it is not possible to directly get a tuple as the result of generating a list comprehension? (I understand I can do tuple([y.x() for y in f])). I don't have a use case, this is purely for my understanding.


回答1:


Some people treat tuples as read-only lists, and that works in some contexts. But that is not the semantic intention of tuples. Lists are intended to be used for variable length structures of homogeneous elements (elements with a shared type). Tuples are intended for fixed length structures in which each indexed position contains a certain type of element.

enumerate(lst) is an example of this. It returns a variable-length list of tuples. Each tuple has exactly two elements, the first of which is always an integer, and the second of which is from lst.

With that understanding, a tuple generator is a bit nonsensical. That is probably why.

Edit:

As for directly generating a tuple, you can do a little bit better than your example. This also works:

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

That passes a generator to the tuple() method, which constructs a tuple, but doesn't create an intermediate list.

To be clear, there is no tuple involved in (y.x() for y in f), but there is a tuple in t = 1, 2, 3. It's not the parens that make the tuple. It's the commas.




回答2:


Question: Why is the first expression not generating a tuple of the values obtained from the generator the way the list is being built?

That is not what is designed to do.
See PEP-289
Tutorial is always a good place to start looking for answers.
Generator Expressions
Expression lists - describes the use of a comma for defining a tuple

So is it true that it is not possible to directly get a tuple as the result of generating a list comprehension?

No -not like a list comprehension, it is a generator. It is designed to yield individual elements for each iteration.



来源:https://stackoverflow.com/questions/19282745/in-python-whats-the-difference-between-a-list-comprehension-with-a-list-and-a-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!