62

我了解函数如何喜欢range()并且zip()可以在 for 循环中使用。但是我希望range()输出一个列表 - 就像seq在 unix shell 中一样。如果我运行以下代码:

a=range(10)
print(a)

输出是range(10),表明它不是列表而是不同类型的对象。zip()打印时有类似的行为,输出类似

<zip object at "hexadecimal number">

所以我的问题是它们是什么,制作它们有什么优势,以及如何在不循环它们的情况下将它们的输出输出到列表中?

4

3 回答 3

96

您必须使用 Python 3。

在 Python 2 中,对象ziprange确实按照您的建议行事,返回列表。它们被更改为类似于生成器的对象,这些对象按需生成元素,而不是将整个列表扩展到内存中。一个优势是在它们的典型用例中效率更高(例如迭代它们)。

“惰性”版本也存在于 Python 2.x 中,但它们有不同的名称,即xrangeitertools.izip.

要将所有输出一次检索到熟悉的列表对象中,您可以简单地调用list迭代并使用内容:

>>> list(range(3))
[0, 1, 2]
>>> list(zip(range(3), 'abc'))
[(0, 'a'), (1, 'b'), (2, 'c')]
于 2013-11-04T21:37:55.877 回答
26

在 Python 3.x. 中,range返回一个范围对象,而不是像在 Python 2.x 中那样的列表。同样,zip现在返回一个 zip 对象而不是列表。

要将这些对象作为列表获取,请将它们放入list

>>> range(10)
range(0, 10)
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> zip('abc', 'abc')
<zip object at 0x01DB7120>
>>> list(zip('abc', 'abc'))
[('a', 'a'), ('b', 'b'), ('c', 'c')]
>>>

虽然乍一看似乎无济于事,但这种行为的改变range实际上zip提高了效率。这是因为 zip 和 range 对象会根据需要生成项目,而不是创建一个列表来一次保存所有项目。这样做可以节省内存消耗并提高运行速度。

于 2013-11-04T21:37:50.517 回答
7

Range(xrange在 python 2.* 中)对象是不可变序列,而 zip(分别itertools.izip)是生成器对象。要从生成器或序列创建列表,只需强制转换为列表。例如:

>>> x = range(10) 
>>> list(x)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

但它们在元素生成方式上有所不同。正常的生成器是可变的,并且如果迭代,它们的内容就会耗尽,而范围是不可变的,并且不要:

>>> list(x) # x is a range-object
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # second cast to list, contents is the same
>>> y = zip('abc', 'abc')
>>> list(y) # y is a generator
[('a', 'a'), ('b', 'b'), ('c', 'c')]
>>> list(y) 
[] # second cast to list, content is empty!
于 2013-11-04T21:41:03.010 回答