iterators and generators

Iterable object (iterable) [iterable object internally implements the __iter__ method, which returns an iterator object]

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> x  =  [ 1 2 3 ]
>>> y  =  iter (x)
>>> z  =  iter (x)
>>>  next (y)
1
>>>  next (y)
2
>>>  next (z)
1
>>>  type (x)
< class  'list' >
>>>  type (y)
< class  'list_iterator' >

An iterator is an iterable type, for example list_iterator,set_iterator

for example:

1
2
3
=  [ 1 2 3 ]
for  elem  in  x:
     ...

The real situation is:

Decompiling this code, you can see that the interpreter explicitly calls the GET_ITERinstruction, which is equivalent to calling iter(x). The FOR_ITERinstruction is to call the next()method and continuously get the next element in the iterator, but you can't see it directly from the instruction, because he Optimized by the interpreter.

 

iterator

An iterator is an object with state, and any object that implements the __iter__ and __next__ (next() in python2) methods is an iterator. __iter__ returns the iterator itself, __next__ returns the next value in the container, or throws an exception if there are no more elements in the container.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class  Fib:
     def  __init__( self ):
         self .prev  =  0
         self .curr  =  1
  
     def  __iter__( self ):
         return  self
  
     def  __next__( self ):
         value  =  self .curr
         self .curr  + =  self .prev
         self .prev  =  value
         return  value
  
>>> f  =  Fib()
>>>  list (islice(f,  0 10 ))
[ 1 1 2 3 5 8 13 21 34 55 ]

Fib is both an iterable object (implementing the __iter__ method) and an iterator implementation (the __next__ method). The instance variables prev and curr maintain the internal state of the iterator each time the next() method is called. Do two things:

  1. Modify the state for the next call to the next() method

  2. Generate the return result for the current call

My ultimate example to help you understand iterators

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class  MyIter:
     def  __init__( self , start = 0 , end = 0 ):
         print ( '程序的init' )
         self .start  =  start
         self .end  =  end
     def  __iter__( self ):
         print ( '我在这里制造了一个迭代器' )
         return  self  # 这个地方如果不return self 那么c 就不具备可迭代的能力
     def  __next__( self ):
         print ( '这里调用 __next__方法' self .start)
         if  self .start <  self .end:
             =  self .start
             self .start  + =  1
             return  i
         else :
             raise  StopIteration()
=  MyIter( 0 5 # 代码到这里只是创造了一个迭代器
 
for  in  c: # 代码到这里 会调用__iter__和__next__ 具有迭代的能力
     print (i)
>>>>>>>>>程序的init
我在这里制造了一个迭代器
这里调用 __next__方法  0
0
这里调用 __next__方法  1
1
这里调用 __next__方法  2
2
这里调用 __next__方法  3
3
这里调用 __next__方法  4
4
这里调用 __next__方法  5

generator

A generator is a special kind of iterator, but this kind of iterator is more elegant. The generator does not need to write __iter__ and __next__ methods, but only needs a yield keyword.

A generator must be an iterator (not vice versa)

 

generator expression

Generator expressions are the generator version of a list comprehension

1
2
3
4
5
>>> a  =  (x * for  in  range ( 10 ))
>>> a
<generator  object  <genexpr> at  0x401f08 >
>>>  sum (a)
285

 

Summarize:

* A container is a collection of elements, str, list, set, dict, file, sockets can all be regarded as containers

  Containers are iterable

* The iterable object implements the __iter__ method, which returns an iterator object

* The iterator holds an internal state field and the user records the return value of the next iteration. It implements the __iter__ and __next__ methods. The iterator will not load all elements into memory at one time, but will return the result when needed

* Generator is a special kind of iterator, the return value is returned by yield

 

 

本文转自http://www.cnblogs.com/mosson/p/8398187.html#_label0

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324853286&siteId=291194637