如果range()是Python 3.3中的生成器,为什么我不能在一个范围上调用next()?

Jef*_*eff 68 python iterator generator typeerror python-3.x

也许我已经成为网络上错误信息的牺牲品,但我认为这更可能只是因为我误解了某些东西.根据我到目前为止所学到的,range()是一个生成器,生成器可以用作迭代器.但是,这段代码:

myrange = range(10)
print(next(myrange))
Run Code Online (Sandbox Code Playgroud)

给我这个错误:

TypeError: 'range' object is not an iterator
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么?我期待这个打印0,并进入下一个值myrange.我是Python的新手,所以请接受我对这个相当基本的问题的道歉,但我无法在其他任何地方找到一个好的解释.

Ole*_*pin 85

range是一类不可变的可迭代对象.他们的迭代行为可以与lists 进行比较:你不能next直接调用它们; 你必须通过使用获得一个迭代器iter.

所以不,range不是发电机.

你可能会想,"他们为什么不让它直接迭代"?好吧,ranges有一些有用的属性,这是不可能的:

  • 它们是不可变的,因此它们可以用作字典键.
  • 他们有start,stopstep属性(因为Python 3.3),countindex方法,它们支持in,len__getitem__操作.
  • 您可以range多次迭代相同的内容.

>>> myrange = range(1, 21, 2)
>>> myrange.start
1
>>> myrange.step
2
>>> myrange.index(17)
8
>>> myrange.index(18)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 18 is not in range
>>> it = iter(myrange)
>>> it
<range_iterator object at 0x7f504a9be960>
>>> next(it)
1
>>> next(it)
3
>>> next(it)
5
Run Code Online (Sandbox Code Playgroud)

  • `range`对象的另一个不错的特性是它们有一个`__contains__`方法,可以用来测试一个值是否在一个范围内:`5 in range(10)=> True` (7认同)
  • 另外:`range(0,10,3)[3]`和`9 in range(0,10,3)`.范围几乎是一个懒惰的列表. (5认同)
  • @Jeff严格来说,是的,这是错误的.该笔记的作者可能意味着在Python 3中`range`是*lazy*(与Python 2相比,它只是一个返回列表的函数). (3认同)
  • @ user3079275“直接可迭代”是用词不当,实际上是“迭代器”。迭代器具有内部状态,因此根据定义是可变的。“可迭代”是可以生成迭代器的对象,无论它是否可变。甚至可变对象本身也通常不是迭代器,而是以可重用的方式生成迭代器(例如,您可以使用两个迭代器在两个不同的位置分别迭代同一列表)。 (2认同)