我的教授和这个人都声称
range
创建了一个值列表。
“注意:range 函数只是返回一个包含数字的列表 从 x 到 y-1。例如,range(5, 10) 返回列表 [5, 6, 7, 8, 9]。”
我认为这是不准确的,因为:
type(range(5, 10))
<class 'range'>
此外,访问由
range
创建的整数的唯一明显方法是迭代它们,这使我相信将 range
标记为列表是不正确的。
range
返回一个列表,但在 Python 3.x 中 range
返回类型为 range
的不可变序列。
Python 2.x:
>>> type(range(10))
<type 'list'>
>>> type(xrange(10))
<type 'xrange'>
Python 3.x:
>>> type(range(10))
<class 'range'>
在 Python 2.x 中,如果您想获取可迭代对象,就像在 Python 3.x 中一样,可以使用
xrange
函数,该函数返回 xrange
类型的不可变序列。
Python 2.x 中
xrange
相对于 range
的优势:
相对于xrange()
的优势很小(因为range()
仍然必须在需要时创建值),除非在内存匮乏的机器上使用非常大的范围或当范围的所有元素都使用时从未使用过(例如当循环通常以break终止时)。xrange()
注:
此外,访问由
创建的整数的唯一明显方法是迭代它们,range()
不。由于 Python 3 中的
range
对象是不可变序列,因此它们也支持索引。引用 range
函数文档,
范围实现了除串联和重复之外的所有常见序列操作
...
ABC,并提供包含测试、元素索引查找、切片和对负索引的支持等功能。collections.abc.Sequence
例如,
>>> range(10, 20)[5]
15
>>> range(10, 20)[2:5]
range(12, 15)
>>> list(range(10, 20)[2:5])
[12, 13, 14]
>>> list(range(10, 20, 2))
[10, 12, 14, 16, 18]
>>> 18 in range(10, 20)
True
>>> 100 in range(10, 20)
False
所有这些都可以通过不可变的
range
序列实现。
最近,我遇到了一个问题,我认为将其包含在这里是合适的。考虑这个 Python 3.x 代码
from itertools import islice
numbers = range(100)
items = list(islice(numbers, 10))
while items:
items = list(islice(numbers, 10))
print(items)
人们会期望这段代码将每十个数字打印为一个列表,直到 99。但是,它会无限运行。你能说出原因吗?
解决方案
因为
返回一个不可变的 sequence,而不是迭代器对象。因此,每当对range
对象执行islice
时,它总是从头开始。将其视为不可变列表的直接替代品。现在问题来了,你将如何解决它?很简单,你只需要从中得到一个迭代器。只需更改即可range
numbers = range(100)
到
numbers = iter(range(100))
现在,是一个迭代器对象,它会记住之前迭代了多长时间。因此,当numbers
迭代它时,它只是从之前结束的位置开始。islice
这要看情况。
在 python-2.x 中,
range
实际上创建一个列表(也是一个序列),而 xrange
创建一个 xrange
对象,可用于迭代值。
另一方面,在 python-3.x 中,
range
创建一个可迭代(或更具体地说,一个序列)
range 创建一个列表。 在这种情况下,仅当多次引用 range 时才使用它,否则使用 xrange,它通过减少内存使用量和有时的时间来创建生成器,因为它具有惰性方法。
xrange 在 python 3.x 中不存在,而 range 代表 xrange 对于 python 2.x
for
带有 range
函数的循环要了解
for i in range()
在 Python3 中的含义,我们首先需要了解 range()
函数的工作原理。
range()
函数使用生成器来生成数字。 它不会一次生成所有数字。
如您所知,
range()
返回range
对象。 range
对象使用相同(少量)的内存,无论它代表的范围大小如何。它仅存储开始、停止和步长值,并根据需要计算单个项目和子范围。
即,仅当
for
循环迭代要求时才生成下一个值。在每次循环迭代中,它生成下一个值并将其分配给迭代器变量i
。
所以这意味着
range()
当循环移动到下一次迭代时一个接一个地产生数字。它节省了大量的内存,这使得 range() 更快更高效。