Python 迭代器 & __iter__方法

迭代器就是重复地做一些事情,可以简单的理解为循环,在python中实现了__iter__方法的对象是可迭代的,实现了next()方法的对象是迭代器,这样说起来有点拗口,实际上要想让一个迭代器工作,至少要实现__iter__方法和next方法。很多时候使用迭代器完成的工作使用列表也可以完成,但是如果有很多值列表就会占用太多的内存,而且使用迭代器也让我们的程序更加通用、优雅、pythonic。

如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

适才发现之前在pydev中使用的语法检查器是python3.2,而解释器是python2.7……罪过罪过,从此篇之后,不出意外都是使用python3.x版本解释器

本文主要举例介绍python的built-in函数iter,
以及类中的两个函数__iter__,__next__。其中作为iterator的对象是类,而不是容器(因为容器或generator作为iterator对象很简单,这里不多说了)

iter函数有两种用法,一种是传一个参数,一种是传两个参数。返回的结果都是返回一个iterator对象。
先说传两个参数的,比如有

i1 = iter(itr, 'c')

 

这个意思是说,返回itr的iterator,而且在之后的迭代之中,迭代出来'c'就立马停止。对这个itr有什么要求呢?这个itr在这里必须是callable的,即要实现__call__函数

再说传一个参数,有

  1. i2 = iter(itr)  
<span style="font-size:18px;">i2 = iter(itr)</span>

这里itr必须实现__iter__函数,这个函数的返回值必须返回一个iterator对象

看例子:

  1. class Itr(object):  
  2.     def __init__(self):  
  3.         self.result = ['a''b''c''d']  
  4.         self.i = iter(self.result)  
  5.           
  6.           
  7.     def __call__(self):  
  8.         res = next(self.i)  
  9.         print("__call__ called, which would return ", res)  
  10.         return res  
  11.   
  12.   
  13.     def __iter__(self):  
  14.         print("__iter__ called")  
  15.         return iter(self.result)  
  16.   
  17.       
  18. itr = Itr()  
  19. # i1必须是callable的,否则无法返回callable-iterator  
  20. i1 = iter(itr, 'c')  
  21. print("i1 = ", i1)  
  22. # i2只需要类实现__iter__函数即可返回  
  23. i2 = iter(itr)  
  24. print("i2 = ", i2)  
  25.   
  26. for i in i1:  
  27.     print(i)  
  28.   
  29. for i in i2:  
  30.     print(i)  
<span style="font-size:18px;">class Itr(object):
    def __init__(self):
        self.result = ['a', 'b', 'c', 'd']
        self.i = iter(self.result)
        
        
    def __call__(self):
        res = next(self.i)
        print("__call__ called, which would return ", res)
        return res


    def __iter__(self):
        print("__iter__ called")
        return iter(self.result)

    
itr = Itr()
# i1必须是callable的,否则无法返回callable-iterator
i1 = iter(itr, 'c')
print("i1 = ", i1)
# i2只需要类实现__iter__函数即可返回
i2 = iter(itr)
print("i2 = ", i2)

for i in i1:
    print(i)

for i in i2:
    print(i)</span>


输出结果是:

  1. i1 =  <callable_iterator object at 0x1349710>  
  2. __iter__ called  
  3. i2 =  <list_iterator object at 0x133a090>  
  4. __call__ called, which would return  a  
  5. a  
  6. __call__ called, which would return  b  
  7. b  
  8. __call__ called, which would return  c  
  9. a  
  10. b  
  11. c  
  12. d  
<span style="font-size:18px;">i1 =  <callable_iterator object at 0x1349710>
__iter__ called
i2 =  <list_iterator object at 0x133a090>
__call__ called, which would return  a
a
__call__ called, which would return  b
b
__call__ called, which would return  c
a
b
c
d</span>


可以看到传入两个参数的i1的类型是一个callable_iterator,它每次在调用的时候,都会调用__cal__函数,并且最后到c就停止了。
而i2就简单的多,itr把自己类中一个容器的迭代器返回就可以了


有朋友可能不满意,对上面的例子只是为了介绍iter()函数传两个参数的功能而写,如果真正想写一个iterator的类,需要使用__next__函数。这个函数每次返回一个值就可以实现迭代了。

  1. class Next(object):  
  2.     def __init__(self, data = 1):  
  3.         self.data = data  
  4.           
  5.           
  6.     def __iter__(self):  
  7.         return self  
  8.       
  9.       
  10.     def __next__(self):  
  11.         print("__next__ called")  
  12.         if self.data > 5:  
  13.             raise StopIteration  
  14.         else:  
  15.             self.data += 1  
  16.             return self.data  
  17. for i in Next(3):  
  18.     print(i)  
<span style="font-size:18px;">class Next(object):
    def __init__(self, data = 1):
        self.data = data
        
        
    def __iter__(self):
        return self
    
    
    def __next__(self):
        print("__next__ called")
        if self.data > 5:
            raise StopIteration
        else:
            self.data += 1
            return self.data
for i in Next(3):
    print(i)</span>


输出结果是:

  1. __next__ called  
  2. 4  
  3. __next__ called  
  4. 5  
  5. __next__ called  
  6. 6  
  7. __next__ called  
<span style="font-size:18px;">__next__ called
4
__next__ called
5
__next__ called
6
__next__ called</span>


很简单把。唯一需要注意下的就是__next__中必须控制iterator的结束条件,不然就死循环了。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值