我在很多帖子/材料中看到过xrange(num)是一个生成器/迭代器。我有几个问题。
如果xrange是迭代器/生成器,则应该使用.next()方法。我不明白为什么.next()方法对下面的情况不起作用。
def generator():
for i in xrange(20): yield i
在上面的例子中,
numbers = generator()
for i in numbers:
if i == 6: break
for i in numbers:
if i == 10: break
print i
>>> 7
8
9
>>> print numbers.next()
11
上述功能也适用于以下类型的对象生成器:
>>> numbers = (x for x in range(100))
如果我使用xrange操作,循环开始从头开始迭代,并且没有next()操作。我知道我们可以采取明智的方式:
for i in xrange(20):
if (#something):
var = i
break
#perform some operations
for i in range(var,20):
#Do something
但我想在var之后循环继续而不使用var。
简而言之,xrange是否存在next()类型的操作。如果是:'如何?' ,否则:'为什么?'
答案 0 :(得分:5)
xrange
是一个可迭代的,所以你可以调用iter
来获取迭代器。
>>> x = xrange(20)
>>> iterator = iter(x)
>>> for i in iterator:
... if i == 6: break
...
>>> iterator.next()
7
答案 1 :(得分:3)
首先你应该注意一个xrange对象不是一个生成器:
>>> xrange_obj = xrange(10000)
>>> type(xrange_obj)
xrange
>>> gen_obj = (x for x in range(10000))
>>> type(gen_obj)
generator
>>> import types
>>> isinstance(xrange_obj, types.GeneratorType)
False
>>> isinstance(gen_obj, types.GeneratorType)
True
是可迭代的(但不是迭代器)
>>> iter(xrange_obj)
<rangeiterator at 0x3e07f930>
>>> iter(xrange_obj).next()
0
最后,正如我在其他答案中没有看到的那样,xrange不是一个生成器而是它自己的对象类型的原因是因为它支持特殊的方法来使它模仿range
。
>>> xrange_obj[1]
1
>>> len(xrange_obj)
10000
>>> gen_obj[1]
TypeError: 'generator' object has no attribute '__getitem__'
>>> len(gen_obj)
TypeError: object of type 'generator' has no len()
答案 2 :(得分:2)
另外,你应该明白迭代器和生成器不是一回事。 iterable 是实现返回迭代器的__iter__
方法的任何Python对象。迭代器还必须实现__iter__
方法,还必须实现next
方法(Python 3中的__next__
)。所以xrange
是可迭代的,但不是迭代器。这是一个迭代器:
class NumberCounter(object):
def __init__(self, size):
self.size = size
self.start = 0
def __iter__(self):
return self
def next(self):
if self.start < self.size:
self.start += 1
return self.start
raise StopIteration
在交互式口译员中:
>>> nc6 = NumberCounter(6)
>>> it = iter(nc6)
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
4
>>> next(it)
5
>>> next(it)
6
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in next
StopIteration
>>> for i in NumberCounter(6):
... print(i)
...
1
2
3
4
5
6
>>>
生成器是一种Python构造,可以帮助您轻松创建迭代器。
来自docs:
生成器是一个用于创建迭代器的简单而强大的工具。他们 像常规函数一样编写,但使用yield语句 每当他们想要返回数据时。每次调用next()时, 生成器从它停止的地方恢复(它记住所有数据 值和最后执行的语句)...任何可能的事情 使用生成器完成也可以使用基于类的迭代器完成 在上一节中描述。什么使发电机如此紧凑是 自动创建__iter __()和next()方法...在 除了自动方法创建和保存程序状态,何时 生成器终止,它们自动引发StopIteration。在 组合,这些功能可以轻松创建没有的迭代器 比编写常规函数更省力。
这是一个发电机:
def number_counter(x):
curr = 1
while curr <= x:
yield curr
curr += 1
在交互式口译员中:
>>> for i in number_counter(6):
... print(i)
...
1
2
3
4
5
6
>>>
这是另一个:
def wacky_gen():
yield 88
yield 2
yield 15
...最后
>>> for i in wacky_gen():
... print(i)
...
88
2
15
>>>