可迭代对象(iterable),只定义了__iter__方法; 字符串、列表、元组、字典、文件;可以通过iter(iterable)方法获取iterator对象,也可以通过list(iterable)for xxx in iterable间接调用__iter__方法
迭代器(iterator), Iteration Protocol: 定义了__iter__和__next__两个方法,__iter__返回迭代器本身(用于for loop),__next__方法返回下一个元素,如果没有元素了,抛出StopIteration异常; for python2, use next; for python3, use __next__
iterator = iter(l) #
iterator2 = l.__iter__()
list(l)
for xxx in l:
yrange
例子1:iterable和iterator是同一个对象。
y = iterable()
list(y)
list(y)
for i in y
只有第一次输出所有值;后续输出未空。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classyrange: def__init__(self, n): self.i = 0 self.n = n
def__iter__(self): print("__iter__1") returnself
defnext(self): ifself.i < self.n: i = self.i self.i += 1 return i else: raise StopIteration()
classzrange_iter: def__init__(self, n): self.i = 0 self.n = n
def__iter__(self): print("__iter__2") # Iterators are iterables too. # Adding this functions to make them so. returnself
defnext(self): ifself.i < self.n: i = self.i self.i += 1 return i else: raise StopIteration()
output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
z = zrange(3) list(z) __iter__1 [0, 1, 2]
list(z) __iter__1 [0, 1, 2]
z = zrange(3) list(z.__iter__()) __iter__1 __iter__2 [0, 1, 2]
list(z.__iter__()) __iter__1 __iter__2 [0, 1, 2]
Generator
Generator functions are ordinary functions defined using yield instead of return. When called, a generator function returns a generator object, which is a kind of iterator - it has a next() method. When you call next(), the next value yielded by the generator function is returned.
use the word “generator” to mean the genearted object and “generator function” to mean the function that generates it.
>>> y = yrange(3) >>> y <generator object yrange at 0x401f30> >>> y.next() 0 >>> y.next() 1 >>> y.next() 2 >>> y.next() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
How to work
When a generator function is called, it returns a generator object without even beginning execution of the function. When next method is called for the first time, the function starts executing until it reaches yield statement. The yielded value is returned by the next call.
>>> deffoo(): ... print"begin" ... for i inrange(3): ... print"before yield", i ... yield i ... print"after yield", i ... print"end" ... >>> f = foo() # 不执行任何语句,返回generator object >>> f.next() # 执行语句直到yield,返回结果 begin before yield0 0 >>> f.next() # 从上一次yield语句的下一句开始执行语句直到再次到达yield,返回结果 after yield0 before yield1 1 >>> f.next() # 从上一次yield语句的下一句开始执行语句直到再次到达yield,返回结果 after yield1 before yield2 2 >>> f.next() # 从上一次yield语句的下一句开始执行语句,由于没有再次到达yield所以抛出StopIteration异常 after yield2 end Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>>
defintegers(): """Infinite sequence of integers.""" i = 1 whileTrue: yield i i = i + 1
defsquares(): for i in integers(): yield i * i
deftake(n, seq): """Returns first n values from the given sequence.""" seq = iter(seq) result = [] try: for i inrange(n): result.append(seq.next()) except StopIteration: pass return result
print take(5, squares()) # prints [1, 4, 9, 16, 25]
Generator Expressions
Generator Expressions are generator version of list comprehensions. They look like list comprehensions, but returns a generator back instead of a list.