python如果想讓一個類被用於for....in 循環,類型list和tuple那樣,可以實現__iter__方法。
這個方法返回一個迭代對象,python的for循環就會不斷調用該迭代對象的next()方法拿到循環的下一個值,直到遇到StopIteration錯誤時退出循環。
class Fib(object):
def __init__(self):
self.a,self.b=0,1 #初始化兩個計數器a,b
def __iter__(self):
return self #實例本身就是迭代對象,故返回自己
def next(self):
self.a,self.b=self.b,self.a+self.b #計算下一個值
if self.a>100000: #退出循環的條件
raise StopIteration()
return self.a
把Fib實例作用於for循環:
for n in Fib():
print n
1
1
2
3
5
...
46368
75025
Fib 實例雖然能作用於for循環,看起來和list有點像,但是,把它當成list來使用還是不行,例如,按下標取元素
print Fib()[5]
此時會報錯:TypeError: 'Fib' object does not support indexing
要實現按下標取元素,需要實現__getitem__()方法
def __getitem__(self,n):
a,b=1,1
for x in range(n):
a,b=b,a+b
return a
按下標獲取元素
f=Fib() print f[0] #1 print f[1] #1 print f[10] #89 print f[100] #573147844013817084101
list 有個切片方法獲取元素
print range(100)[5:10] #[5, 6, 7, 8, 9]
對於Fib卻報錯,原因是__getitem__傳入的參數可能是一個int,也可能是一個切片對象slice,需要做判斷
def __getitem__(self, n):
if isinstance(n, int):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
if isinstance(n, slice):
start = n.start
stop = n.stop
a, b = 1, 1
L = []
for x in range(stop):
if x >= start:
L.append(a)
a, b = b, a + b
return L
試試Fib的切片
f=Fib() print f[0:5] #==>[1, 1, 2, 3, 5] print f[:10] # ==>[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
