使用range()
功能创建list
时,我遇到了一些问题
做一些实验,我得到以下内容:
>>> isinstance([], list)
True
>>> isinstance(range(10), list)
False
另外,阅读其文档:
>>> print(range.__doc__)
range(stop) -> range object
range(start, stop[, step]) -> range object
Return a virtual sequence of numbers from start to stop by step.
我目前使用list(range())
确实有一个解决方法,但问题仍然存在。什么是虚拟的数字序列?
答案 0 :(得分:21)
range()
对象按需计算数字,例如迭代时或尝试访问特定索引时:
>>> r = range(2, 80, 3)
>>> len(r)
26
>>> r[15]
47
>>> 42 in r
False
>>> r[:10]
range(2, 32, 3)
这是一个序列,因为该对象支持成员资格测试,索引,切片并具有长度,就像列表或元组一样。但是,与列表或元组不同,它实际上并不包含内存序列中的所有整数,使其成为虚拟。
当您在list()
对象上调用range()
时,您正在创建一个包含该范围内所有整数的新序列,但您现在正在存储所有这些整数:
>>> r_list = list(r)
>>> r_list
[2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77]
这也是一个序列,但它需要更多的内存,因为现在所有整数都在前面生成,你是否会使用它们。所以列表或元组是具体的序列。
使用sys.getsizeof()
function,我们可以计算每个对象使用的内存量:
>>> import sys
>>> sys.getsizeof(r)
48
>>> sys.getsizeof(r_list) + sum(sys.getsizeof(i) for i in r_list)
1072
列表对象使用22倍的内存;那是因为它包含26个整数对象。
要解决有关您问题的评论,range()
个对象不 iterators。迭代器根据需要逐个生成值,但无法编制索引,它们只生成一次的所有值,并且它们没有长度。您可以使用iter()
function:{/ p>从range()
对象生成迭代器
>>> iter(r)
<range_iterator object at 0x10aea23f0>
>>> r_iter = iter(r)
>>> len(r_iter)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'range_iterator' has no len()
>>> list(r_iter)
[2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77]
>>> list(r_iter)
[]
但是一旦耗尽,迭代器将不再产生相同的范围。
以上所有内容主要适用于Python 3;在Python 2中,类型被称为xrange()
,它的能力更受限制(它不支持切片,只能处理整数&lt; sys.maxint
)。