python中的generator, iterator, iterabel

Posted billiepander

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python中的generator, iterator, iterabel相关的知识,希望对你有一定的参考价值。

先来看看如果遇到一个对象,如何判断其是否是这三种类型:

1 from types import GeneratorType
2 from collectiuons import Iterable, Iterator
3 
4 isinstance( xx, GeneratorType )
5 isinstance( xx, Iterable )
6 isinstance( xx, Iterator )

 

生成器对象:

  生成器是一个通过yield关键字构建的函数,其返回一个generator对象,同时其又是一个iterator对象,因为其实现了__iter__与next方法

In[4]: def gene(k):
...     for i in xrange(0, k):
...         yield i
...         
In[5]: ge = gene(6)
In[6]: type(ge)
Out[6]: generator
In[8]: dir(ge)
Out[8]: [ ...,__iter__, next, ... ]     
In[9]: isinstance(ge, collections.Iterator)
Out[9]: True

  生成器的一个特点是只能用一次

In[11]: for i in ge: 
...     print i
...     
0
1
2
3
4
5
In[12]: ge.next()
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/IPython/core/interactiveshell.py", line 2820, in run_code
    exec code_obj in self.user_global_ns, self.user_ns
  File "<ipython-input-12-b9172cd6050f>", line 1, in <module>
    ge.next()
StopIteration

 

迭代器对象:

  实现了__iter__与__next__方法的对象。

  __iter__返回一个实例作为最终使用的iterator对象--for...in...语句初始化时使用,next方法是后面每次迭代iterator对象时调用的方法

class Counter(object):
    def __init__(self, low, high):
        self.current = low
        self.high = high

    def __iter__(self):
        # Returns itself as an iterator object
        return self

    def next(self):
        # Returns the next value till current is lower than high
        if self.current > self.high:
            raise StopIteration
        else:
            self.current += 1
            return self.current - 1

>>> c = Counter(5,10)
>>> for i in c:
...   print(i, end=‘ ‘)
...
5 6 7 8 9 10
>>> for i in c:
...  pritn i
...
# 无输出
>>> c.next()
Traceback (most recent call last):
  File "<ipython-input-12-b9172cd6050f>"
    c.next()
StopIteration

 

可迭代对象:

  可迭代对象就是用于for...in...循环的

  不同于上面两种,其需要可以多次for...in...使用

  通过generator写可迭代对象:

  将__iter__写成生成器函数。注意for...in...时初始化时调用__iter__函数使得counter为low, 而后执行的都是yield所影响区域的了【1】,除非下次再执行for...in...语句才会调用到counter初始化那句,这样也就实现了复用。但是有个问题是此时Counter的实例就既不是generator也不是iterator对象了。故其也没法调用next方法

class Counter(object):
    def __init__(self, low, high):
        self.low = low
        self.high = high

    def __iter__(self):
        counter = self.low
        while self.high >= counter:
            yield counter
            counter += 1

obj = Counter(5, 10)
print isinstance(obj, Iterator)
print isinstance(obj, GeneratorType)
print type(obj)
for i in obj:
    print i
obj.next()

False
False
<class ‘__main__.Counter‘>
5
6
7
8
9
10

Traceback (most recent call last):
File "/home/pd/..."
obj.next()
AttributeError: ‘Counter‘ object has no attribute ‘next‘

 

注释【1】:

In [1]: def gener(k):                                                            
   ...:     print "====initial===="                                              
   ...:     for i in range(0, k):                                                
   ...:         print "before yield"                                             
   ...:         yield i                                                          
   ...:         print "after yield"                                              
   ...:     print "*****end******"                                               
   ...:                                                                          
                                                                                 
In [2]: g = gener(3)
In [3]: for i in g:                                                              
   ...:     print g                                                              
   ...:                                                                          
====initial====                                                                  
before yield                                                                     
<generator object gener at 0x7fbc8d15e870>                                       
after yield                                                                      
before yield                                                                     
<generator object gener at 0x7fbc8d15e870>                                       
after yield                                                                      
before yield                                                                     
<generator object gener at 0x7fbc8d15e870>                                       
after yield                                                                      
*****end****** 

 

参考:

  http://pymbook.readthedocs.io/en/latest/igd.html

以上是关于python中的generator, iterator, iterabel的主要内容,如果未能解决你的问题,请参考以下文章

Python中的Comprehensions和Generations

python中的生成器 generator

python中的generator, iterator, iterabel

python yield generator 详解

python yield generator 详解

Iterator和Iteratable的区别,介绍