range() 真的会创建列表吗? [英] Does range() really create lists?
问题描述
我的教授和这个人都声称range
创建一个值列表.
"注意:range 函数只返回一个包含数字的列表从 x 到 y-1.例如,range(5, 10) 返回列表 [5, 6, 7, 8,9]."
我认为这是不准确的,因为:
type(range(5, 10))<类范围">
此外,访问由 range
创建的整数的唯一明显方法是遍历它们,这让我相信将 range
标记为列表是不正确的.
在 Python 2.x 中,range
返回一个列表,但在 Python 3.x range
返回一个不可变序列,类型为 range
.
Python 2.x:
<预><代码>>>>类型(范围(10))<输入列表">>>>类型(xrange(10))<输入'xrange'>Python 3.x:
<预><代码>>>>类型(范围(10))<类范围">在 Python 2.x 中,如果你想获得一个可迭代对象,比如在 Python 3.x 中,你可以使用 xrange
函数,它返回类型为 xrange
.
xrange
在 Python 2.x 中相对于 range
的优势:
xrange()
相对于 range()
的优势是微乎其微的(因为 xrange()
仍然需要在需要时创建值它们)除非在内存不足的机器上使用非常大的范围或从不使用范围的所有元素时(例如当循环通常以 break 终止时).
注意:
<块引用>此外,访问由 range()
创建的整数的唯一明显方法是遍历它们,
没有.由于 Python 3 中的 range
对象是不可变序列,因此它们也支持索引.引用 range
函数文档,
Ranges 实现了除连接和重复之外的所有常见序列操作
...
Range 对象实现了 collections.abc.Sequence
ABC,并提供包含测试、元素索引查找、切片和支持负索引等功能.
例如
<预><代码>>>>范围(10, 20)[5]15>>>范围(10, 20)[2:5]范围(12, 15)>>>列表(范围(10, 20)[2:5])[12, 13, 14]>>>列表(范围(10、20、2))[10, 12, 14, 16, 18]>>>18 范围内 (10, 20)真的>>>100 范围内 (10, 20)错误的所有这些都可以通过不可变的 range
序列实现.
最近,我遇到了一个问题,我认为将其包含在这里是合适的.考虑这个 Python 3.x 代码
from itertools import islice数字 = 范围(100)项目 = 列表(islice(数字,10))而项目:项目 = 列表(islice(数字,10))打印(项目)
人们希望这段代码每十个数字打印一个列表,直到 99.但是,它会无限运行.你能说出原因吗?
解决方案
因为
range
返回一个不可变的 sequence,而不是一个迭代器对象.因此,每当在range
对象上执行islice
时,它总是从头开始.将其视为不可变列表的替代品.现在问题来了,你将如何解决它?很简单,你只需要从中得到一个迭代器.只需改变numbers = range(100)
到numbers = iter(range(100))
现在,numbers
是一个迭代器对象,它会记住它之前被迭代了多长时间.所以,当islice
迭代它时,它只是从它之前结束的地方开始.
Both my professor and this guy claim that range
creates a list of values.
"Note: The range function simply returns a list containing the numbers from x to y-1. For example, range(5, 10) returns the list [5, 6, 7, 8, 9]."
I believe this is to be inaccurate because:
type(range(5, 10))
<class 'range'>
Furthermore, the only apparent way to access the integers created by range
is to iterate through them, which leads me to believe that labeling range
as a lists is incorrect.
In Python 2.x, range
returns a list, but in Python 3.x range
returns an immutable sequence, of type range
.
Python 2.x:
>>> type(range(10))
<type 'list'>
>>> type(xrange(10))
<type 'xrange'>
Python 3.x:
>>> type(range(10))
<class 'range'>
In Python 2.x, if you want to get an iterable object, like in Python 3.x, you can use xrange
function, which returns an immutable sequence of type xrange
.
Advantage of xrange
over range
in Python 2.x:
The advantage of
xrange()
overrange()
is minimal (sincexrange()
still has to create the values when asked for them) except when a very large range is used on a memory-starved machine or when all of the range’s elements are never used (such as when the loop is usually terminated with break).
Note:
Furthermore, the only apparent way to access the integers created by
range()
is to iterate through them,
Nope. Since range
objects in Python 3 are immutable sequences, they support indexing as well. Quoting from the range
function documentation,
Ranges implement all of the common sequence operations except concatenation and repetition
...
Range objects implement the
collections.abc.Sequence
ABC, and provide features such as containment tests, element index lookup, slicing and support for negative indices.
For example,
>>> 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
All these are possible with that immutable range
sequence.
Recently, I faced a problem and I think it would be appropriate to include here. Consider this Python 3.x code
from itertools import islice
numbers = range(100)
items = list(islice(numbers, 10))
while items:
items = list(islice(numbers, 10))
print(items)
One would expect this code to print every ten numbers as a list, till 99. But, it would run infinitely. Can you reason why?
Solution
Because the
range
returns an immutable sequence, not an iterator object. So, wheneverislice
is done on arange
object, it always starts from the beginning. Think of it as a drop-in replacement for an immutable list. Now the question comes, how will you fix it? Its simple, you just have to get an iterator out of it. Simply change
numbers = range(100)
to
numbers = iter(range(100))
Now,numbers
is an iterator object and it remembers how long it has been iterated before. So, when theislice
iterates it, it just starts from the place where it previously ended.
这篇关于range() 真的会创建列表吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!