Reprint: The original writing is good!
Original address: Http://www.cnblogs.com/kaituorensheng/p/3826911.html#_label0
Read Catalogue
- 1. iterators
- 2. Generator
- 3. Reference
Back to top of 1. Iterators
Iterators are a way to access the elements of a collection. An iterator object is accessed from the first element of the collection, knowing that all of the elements have been accessed and finished. Iterators can only move forward without going backwards, but that's fine, because people seldom retreat in the middle of an iteration.
1.1 Advantages of using iterators
For primitive data structures that support random access (such as tuple, list), there is no advantage over the index access of the iterator and the classic for loop, but the index value is lost (you can use the built-in function enumerate () to retrieve the index value). But for data structures that cannot be accessed randomly (such as set), iterators are the only way to access elements.
In addition, one of the great advantages of iterators is that they do not require that all elements in the entire iteration be prepared in advance. An iterator computes an element only when it iterates over it, and before or after that, the element may not exist or be destroyed. This feature makes it particularly useful for traversing large or infinite collections, such as several G files, or Fibonacci sequences, and so on.
The greater credit for iterators is the provision of an interface for a unified access collection, which can be accessed using iterators as long as the __iter__ () method object is defined.
There are two basic methods for iterators
- Next method: Returns the next element of the iterator
- __iter__ method: Returns the Iterator object itself
The following is an example of how to generate Fibonacci numbers to illustrate why iterators
Code 1
Def FAB (max): N, a, b = 0, 0, 1 while n < max: print B A, B = B, a + b n = n + 1
Printing with print directly in the function fab (max) causes the reusability of the function to be poor, because Fab returns none. Other functions cannot get the sequence returned by the FAB function.
Code 2
Def FAB (max): L = [] n, a, b = 0, 0, 1 while n < max: l.append (b) A, B = B, a + b n = n + 1 return L
Code 2 satisfies the need for reusability, but takes up memory space, preferably not.
Code 3
Contrast
For I in range (+): Pass
For I in Xrange (£): Pass
The previous one returns a list of 1000 elements, the second one returns an element in each iteration, so you can use iterators to solve the problem of reusable space
Class Fab (object): def __init__ (self, max): Self.max = Max SELF.N, self.a, self.b = 0, 0, 1 def __iter__ (s ELF): return self def next: if SELF.N < self.max: r = self.b self.a, self.b = self.b, SELF.A + self.b SELF.N = SELF.N + 1 return R raise Stopiteration ()
Perform
123456789 |
>>> for key in Fabs( 5 ): print key 1 1 2 3 5 |
The Fabs class continuously returns the next number of columns through next (), and memory consumption is always constant
1.2 Using iterators
Use the built-in factory function iter (iterable) to get an iterator object:
1234 |
>>> lst = range( 5 ) >>> it = iter(lst) >>> it <listiterator object at 0 x 01 A 63110 > |
The next element can be accessed using the next () method:
123456 |
>>> it.next() 0 >>> it.next() 1 >>> it.next() 2 |
Python handling iterator out of bounds is throwing stopiteration exception
123456789101112 |
>>> it.next()
3
>>> it.next
<method-wrapper
‘next‘
of listiterator object at
0
x
01
A
63110
>
>>> it.next()
4
>>> it.next()
Traceback (most recent call last):
File
"<pyshell#27>"
, line
1
, in <module>
it.next()
StopIteration
|
Understanding the Stopiteration, you can use iterators to traverse the
LST = range (5) it = iter (LST) try: While True: val = it.next () print valexcept stopiteration: Pass
Results
In fact, because iterators are so common, python specifically makes the syntax sugar for the iterator for the FOR keyword. In the For loop, Python automatically calls the Factory function iter () to get the iterator, automatically calls next () to get the element, and completes the work of checking the stopiteration exception. As follows
>>> a = (1, 2, 3, 4) >>> for key in a: print key 1234
First Python invokes the ITER function iterator on the object after the keyword in, and then calls the iterator's next method to get the element until the stopiteration exception is thrown.
1.3 Defining iterators
The following example--Fibonacci sequence
#-*-coding:cp936-*-class fabs (object): def __init__ (Self,max): Self.max = Max SELF.N, self.a, self.b = 0, 0, 1 #特别指出: The No. 0 item is 0, the 1th item is the first 1. The entire sequence starts from 1 def __iter__ (self): return self def next (self): if SELF.N < self.max: r = self.b self.a, self.b = self.b, SELF.A + self.b SELF.N = SELF.N + 1 return r R Aise stopiteration () print fabs (5) for key in Fabs (5): print key
Results
123456 |
<__main__.Fabs object at 0 x 01 A 63090 > 1 1 2 3 5 |
Back to top of 2. Generator
The function with yield is called the generator (generator) in Python, with several examples (or the generation of Fibonacci sequence descriptions).
You can see that code 3 is far from the code 1 concise, the generator (yield) can keep the code 1 concise, but also maintain the effect of code 3
Code 4
Def FAB (max): N, a, b = 0, 0, 1 while n < max: yield b A, B = B, a + b n = n + 1
Perform
123456789 |
>>> for N in Fab ( 5 &NBSP;&NBSP;&NBSP;&NBSP; print n 1 1 2 3 5 |
Simply put, the function of yield is to turn a function into a generator, the function with yield is no longer a normal function, the Python interpreter treats it as a generator, the call to Fab (5) does not execute the FAB function, but instead returns an it Erable Object ! When the For loop executes, each loop executes the code inside the FAB function, and when it executes to yield B, the FAB function returns an iteration value , and the next iteration, the code proceeds from the next statement of Yield B, and the local variable of the function looks and The last time the interrupt was executed is exactly the same, and the function continues until the yield is encountered again. It looks as if a function was interrupted several times by yield during normal execution, and each break returns the current iteration value through yield.
You can also call the next () Method of Fab (5) Manually (because Fab (5) is a generator object with the next () method) so that we can see more clearly the execution process of the Fab:
12345678910111213 |
>>> f = Fab ( 3 ) >>> F.next () 1 >>> f.next () 1 >>> f.next () 2 >>> f.next () traceback (most recent call last): &NBSP;&NBSP; file "<pyshell#62>" 1 &NBSP;&NBSP;&NBSP;&NBSP; f.next () stopiteration |
return effect
In a generator, if there is no return, the default execution is done to the function, and if return is encountered, the stopiteration terminate iteration is thrown directly if return is executed during execution. For example
123456789 |
>>> s = fab( 5 ) >>> s.next() 1 >>> s.next() Traceback (most recent call last): File "<pyshell#66>" , line 1 , in <module> s.next() StopIteration |
Code 5 File Read
def read_file (Fpath): block_size = 1024x768 with open (Fpath, ' RB ') as F: While True: BLOCK = F.read (block_ SIZE) if block: yield block else: return
Calling the Read () method directly on a file object causes unpredictable memory consumption. A good approach is to use fixed-length buffers to continuously read the contents of the file. With yield, we no longer need to write an iterative class of read files, so we can easily implement file reads.
Back to Top
3. ReferencePython Functional Programming Guide (iii): Iterator Python yield usage analysis
Python iterator generator (GO)