# 迭代器

```#!/usr/bin/env Python
# coding=utf-8

"""
the interator as range()
"""
class MyRange(object):
def __init__(self, n):
self.i = 0
self.n = n

def __iter__(self):
return self

def next(self):
if self.i < self.n:
i = self.i
self.i += 1
return i
else:
raise StopIteration()

if __name__ == "__main__":
x = MyRange(7)
print "x.next()==>", x.next()
print "x.next()==>", x.next()
print "------for loop--------"
for i in x:
print i```

```\$ python 21401.py
x.next()==> 0
x.next()==> 1
------for loop--------
2
3
4
5
6```

`__iter__()` 是类中的核心，它返回了迭代器本身。一个实现了`__iter__()`方法的对象，即意味着其实可迭代的。

```if __name__ == "__main__":
x = MyRange(7)
print list(x)
print "x.next()==>", x.next()```

```\$ python 21401.py
[0, 1, 2, 3, 4, 5, 6]
x.next()==>
Traceback (most recent call last):
File "21401.py", line 26, in <module>
print "x.next()==>", x.next()
File "21401.py", line 21, in next
raise StopIteration()
StopIteration```

```#!/usr/bin/env Python
# coding=utf-8
"""
compute Fibonacci by iterator
"""
__metaclass__ = type

class Fibs:
def __init__(self, max):
self.max = max
self.a = 0
self.b = 1

def __iter__(self):
return self

def next(self):
fib = self.a
if fib > self.max:
raise StopIteration
self.a, self.b = self.b, self.a + self.b
return fib

if __name__ == "__main__":
fibs = Fibs(5)
print list(fibs)```

```\$ python 21402.py
[0, 1, 1, 2, 3, 5]```

```range(...)
range(stop) -> list of integers
range(start, stop[, step]) -> list of integers

>>> dir(range)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']```

`range()` 的帮助文档和方法中可以看出，它的结果是一个列表。但是，如果用 `help(xrange)` 查看：

```class xrange(object)
|  xrange(stop) -> xrange object
|  xrange(start, stop[, step]) -> xrange object
|
|  Like range(), but instead of returning a list, returns an object that
|  generates the numbers in the range on demand.  For looping, this is
|  slightly faster than range() and more memory efficient.```

`xrange()` 返回的是对象，并且进一步告诉我们，类似 `range()`，但不是列表。在循环的时候，它跟 `range()` 相比“slightly faster than range() and more memory efficient”，稍快并更高的内存效率（就是省内存呀）。查看它的方法：

```>>> dir(xrange)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__len__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']```

```>>> a = ["name", "age"]
>>> b = ["qiwsir", 40]
>>> zip(a,b)
[('name', 'qiwsir'), ('age', 40)]```

```>>> zip(range(4), xrange(100000000))
[(0, 0), (1, 1), (2, 2), (3, 3)]```