python让实例做用于for循环并当作list来使用

python若是想让一个类被用于for....in  循环,类型list和tuple那样,能够实现__iter__方法。python

这个方法返回一个迭代对象,python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。app

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来使用仍是不行,例如,按下标取元素blog

print  Fib()[5]
此时会报错:TypeError: 'Fib' object does not support indexingget

要实现按下标取元素,须要实现__getitem__()方法it

   def  __getitem__(self,n):
        a,b=1,1
        for x  in range(n):
            a,b=b,a+b
        return  a

 按下标获取元素io

f=Fib()
print  f[0]   #1
print  f[1]   #1
print  f[10]   #89
print f[100]   #573147844013817084101

 list 有个切片方法获取元素for循环

print  range(100)[5:10]     #[5, 6, 7, 8, 9]

 对于Fib却报错,缘由是__getitem__传入的参数多是一个int,也多是一个切片对象slice,须要作判断class

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的切片object

f=Fib()
print f[0:5]     #==>[1, 1, 2, 3, 5]

print f[:10]  # ==>[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
相关文章
相关标签/搜索