Python-iterator and generator, python-generator
Refer:
Http://python.jobbole.com/81911/
Http://www.cnblogs.com/kaituorensheng/p/3826911.html
1. iterator
An iterator is a way to access collection elements. The iterator object is accessed from the first element of the set until all elements are accessed. The iterator can only move forward without moving back, but there is nothing to do with it, because people seldom go back on the way of iteration.
1. Advantages of the iterator
For data structures (such as tuple and list) that support random access in the native, The iterator has no advantage over index access in the classic for loop, instead, the index value is lost (you can use the built-in function enumerate () to retrieve the index value ). However, for data structures that cannot be accessed randomly (such as set), The iterator is the only way to access elements. The iterator is a class containing the next function.
In addition, the major advantage of the iterator is that it is not required to prepare all elements in the entire iteration process in advance. The iterator calculates an element only when it iterates to an element. Before or after this, the element may not exist or be destroyed. This feature makes it especially suitable for Traversing large or infinite sets, such as several G files or Fibonacci series.
The primary benefit of the iterator is that it provides a unified interface for accessing the set. As long as the _ iter _ () method object is defined, the iterator can be used for access, when the python handler is out of bounds, A StopIteration exception is thrown.
The iterator has two basic methods:
- Next method: return the next element of the iterator.
- _ Iter _ method: return the iterator object itself
The following uses the generation of the Fibonacci series as an example to explain why the iterator is used:
# This method occupies memory resources def fab (max): n, a, B = 0, 0, 1 l = [] while n <max: a, B = B, a + B l. append (B) n = n + 1 return l # The iterator can be used to solve the problem of space occupation. class Fab (object): def _ init _ (self, max): self. max = max self. n, self. a, self. B = 0, 0, 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 raise StopIteration () # Run the code from iterator import fabfor k in fab (5): print (k) # Use the built-in factory function iter (iterable) get the iterator object: for I in iter (fab): print (I)
Ii. Generator
Functions with yield are called generator (generator function) in Python. The list of things that generator expressions can do can basically be parsed, but when the sequence to be processed is large, list resolution is charged for memory usage.
Def fab (max): n, a, B = 0, 0, 1 while n <max: # Stop every execution to yield, returns the current value of the variable yield B a, B = B, a + B n = n + 1 after yield.
In short, yield is used to convert a function into a generator. A function with yield is no longer a common function. The Python interpreter regards it as a generator and calls fab (5) instead of executing the fab function,Iterable object! During for loop execution, the internal code of the fab function is executed in each loop,RunYield B, the fab function isReturns an iteration value.In the next iteration, the Code continues to run from the next statement of yield B, and the local variable of the function looks exactly the same as before the last interrupted execution, so the function continues to run, until yield is encountered again. It seems that a function is interrupted several times by yield during normal execution, and the current iteration value is returned through yield for each interruption.
In a generator, if there is no return, the function is executed by default. If return is encountered, if return is executedThrow StopIteration to terminate Iteration.
Def g2 (): yield 'a 'Return yield 'B' g = g2 () # The program stays at the position after the yield 'A' statement is executed. Next (g) # The program finds that the next statement is return, # The StopIteration exception is thrown, so that the yield 'B' statement will never be executed. Next (g)
Methods supported by the generator
def g4(): yield 1 yield 2 yield 3print(dir(g4()))['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
Close ()
Manually close the generator function. The StopIteration exception will be returned directly in subsequent calls.
Def g4 (): yield 1 yield 2 yield 3g = g4 () next (g) g. close () next (g) # after closing, the yield 2 and yield 3 statements no longer work Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
Send ()
The biggest feature of a generator function is that it can accept a variable passed in from outside and return the result based on the variable content. This is the most difficult part of generator functions and the most important part. The coroutine I will talk about later depends on it.
- You can use g. send (None) or next (g) to start the generator function and run it at the end of the first yield statement. At this point, the yield statement is executed, but the receive is not assigned a value. Yield value outputs the initial value 0. Note: only send (None) is allowed when the generator function is started. If you try to input other values, an error message is displayed.
- Through g. send ('aaa'), aaa is passed in, and the value is assigned to receive. Then, the value is calculated and returned to the while header. The yield value statement is executed to stop. In this case, yield value outputs "got: aaa" and then suspends it.
- After g. send (3), step 1 is repeated and the output result is "got: 3 ″
- When we use g. send ('end'), the program executes the break and then releases the loop. After the entire function is executed, a StopIteration exception occurs.
def gen(): value=0 while True: receive=yield value if receive=='end': break value = 'got: %s' % receiveg=gen()print(g.send(None))print(g.send('aaa'))print(g.send(3))print(g.send('end'))
Throw ()
It is used to send an exception to the generator function to end system-defined exceptions or custom exceptions. Throw () directly runs the exception and ends the program, or consumes a yield, or directly ends at the end of the program without the next yield.
- Print (next (g): The normal value is output and stays before yield 'normal value 2.
- Because g. throw (ValueError), so all subsequent try statements will be skipped, that is, the yield 'normal value 2' will not be executed, and then enter the retry t statement to print the we got ValueError here. Then enter the while statement again, consuming a yield, so the normal value is output.
- Print (next (g) will execute the yield 'normal value 2' statement and stay at the position after the statement is executed.
- G. throw (TypeError): it will jump out of the try statement, so that print ('where') will not be executed, then execute the break statement, jump out of the while loop, and then reach the end of the program, so it ran out of the StopIteration exception.
def gen(): while True: try: yield 'normal value' yield 'normal value 2' print('here') except ValueError: print('we got ValueError here') except TypeError: break g=gen()print(next(g))print(g.throw(ValueError))print(next(g))print(g.throw(TypeError))
Summary:
According to duck model theory, the generator is an iterator that can be iterated using.
When you execute next (generator) for the first time, the program is suspended after the yield statement is executed, and all parameters and statuses are saved. When next (generator) is executed again, it will be executed from the suspended state. When a program ends or a StopIteration occurs, the loop ends.
You can pass in parameters through generator. send (arg), which is the coroutine model.
You can pass in an exception through generator. throw (exception. The throw statement consumes a yield. You can use generator. close () to manually close the generator.
Next () is equivalent to send (None)