为什么将range对象转换为生成器会导致生成一个`range_iterator`对象?

3

这不是为什么反转范围时需要range_iterator?的重复问题。如果您查看该问题,您将了解原因。

我的问题涉及从range生成的生成器与任何其他迭代器之间的区别,以及为什么要进行区分:

In [500]: iter(range(5))
Out[500]: <range_iterator at 0x10987f810>

Whereas...

In [506]: (i for i in range(4))
Out[506]: <generator object <genexpr> at 0x10a025fc0>

那么,为什么要进行这种区分,它有什么优点呢?
1个回答

7

简单来说,range不是一个迭代器:

In [32]: r = range(10)

In [33]: next(r)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-33-0b5056469c9c> in <module>()
----> 1 next(r)

TypeError: 'range' object is not an iterator

range 是一种序列类型,和其他容器一样,iter 返回一个相应的迭代器对象:

In [34]: iter(list())
Out[34]: <list_iterator at 0x112197cc0>

In [35]: iter(tuple())
Out[35]: <tuple_iterator at 0x112107be0>

In [36]: iter(dict())
Out[36]: <dict_keyiterator at 0x1142eef98>

通常,容器是可迭代的(iterables),而不是迭代器(iterators)。它们实现了__iter__方法,而迭代器则实现了__iter____next__方法。

请注意,您标题中的术语有些不准确,并且我认为您混淆了生成器、迭代器和可迭代对象。 iter(obj)并不返回一个生成器(generator),而是返回一个迭代器对象。生成器是一种语言结构,允许简洁地编写迭代器。由生成器函数返回的generator对象就是迭代器。

In [37]: def mygen():
    ...:     yield 1
    ...:     yield 2
    ...:

In [38]: g = mygen()

In [39]: g
Out[39]: <generator object mygen at 0x1121778e0>

In [40]: next(g)
Out[40]: 1

In [41]: iter(g) is g
Out[41]: True

最后,生成器表达式是编写生成器的更方便的方式!
In [44]: (i for i in range(10) if i % 2 == 0)
Out[44]: <generator object <genexpr> at 0x10de89990>

In [45]: next(_)
Out[45]: 0

那么__repr__只是用来帮助识别生成器来源的吗? - cs95
谢谢,这很有道理。 - cs95
@cᴏʟᴅsᴘᴇᴇᴅ 是的。只需记住生成器、可迭代对象、迭代器和容器之间的区别。range是一个容器(序列),它是可迭代的。 - juanpa.arrivillaga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接