Yield and pythonyield of python Generator

Source: Internet
Author: User

Yield and pythonyield of python Generator

For details, refer to [Python yield Usage Analysis] and [differences between Python xrange and range ].

 

A function with yield is a generator, which is different from a common function. Generating a generator looks like a function call, but does not execute any function code until it calls next () (next () is automatically called in the for loop to start execution. Although the execution process is still executed according to the function process, every execution of a yield statement is interrupted and an iteration value is returned. The next statement of yield continues to be executed during the next execution. 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.

The advantage of yield is obvious. By Rewriting a function as a generator, the iteration capability is achieved. Compared to calculating the next () value by using the Instance Storage status of the class, the Code is not only concise, the execution process is clear.

 

First, let's look at range and xrange:

for i in range(1000): pass

The above code will generate a List containing 1000 elements, and the code:

for i in xrange(1000): pass

The next value is returned in each iteration, and the memory space usage is small. Because xrange does not return List, but returns a generator (List is an iterative object ).

An Iteration object can return an iterator object by calling the iter method, and then perform for loop access:

Class Iterable _: def _ iter _ (self): return iter ([1, 2, 3]) it = iter (Iterable _())) for I in it: print "iterable:" + str (I) # output iterable: 1 iterable: 2 iterable: 3
View Code

 

Range:

A = range () print type (a) # output <type 'LIST'> print a # output [, 4] print a [0], a [1] # output 0, 1

Xrange:

A = xrange (0, 5) print type (a) # output <type 'xrange'> print a # output xrange (5) print a [0], a [1] # output 0, 1

The iterator must be an iterable object. It contains the next (Python 2) method, the _ next _ (Python 3) method, and the _ iter _ (return self) method) A special object of the method. For a generator, it must be an iterator that can access the elements in it through the for loop,An iterator is not necessarily a generator..

There are two ways to define the iterator. The first is to use the yield keyword, and the other is the generator expression "()". Adding the yield keyword to a method body becomes a generator. Yield is used to return a generator, which saves the current function status and records the running status when the worker function is called next. When the function does not run in the next running state, the next method is called again, and the StopIteration exception is thrown. Generator has the characteristics of iteratorFor example, only forward traversal is supported. Of course, the generator also has its own method, such as the send method. You can use send to define the values in the current generator. Onacci)

1. The most common:

def fab(max):    n, a, b = 0, 0, 1    while n < max:        print b        a, b = b, a + b        n = n + 1

 

2. To improve the reusability of fab functions, it is best to return a List as follows:

def fab(max):    n, a, b = 0, 0, 1    L = []    while n < max:        L.append(b)        a, b = b, a + b        n = n + 1    return Lfor n in fab(5):        print n 

 

3. the memory occupied by this function during running will increase with the increase of the max parameter, so it is best not to use List to save the intermediate results, but to iterate through the iterable object, with iterable, we can rewrite the fab function into a class that supports iterable:

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()
View Code

The Fab class continuously returns the next number of columns through next (), and the memory usage is always constant:

>>> for n in Fab(5): ...     print n ...
View Code

 

4. However, the code of this version rewritten by class is far less concise than the fab function of the first version. Use yield:

def fab(max):     n, a, b = 0, 0, 1     while n < max:         yield b         # print b         a, b = b, a + b         n = n + 1

Compared with the first version, the call does not change as long as print B is changed to yield B:

>>> for n in fab(5): ...     print n ... 1 1 2 3 5

Yield is used to convert a function into a generator. The Python interpreter regards it as a generator. Calling fab (5) does not execute the fab function, but returns an iterable object! During for loop execution, code in the fab function is executed in each loop. When yield B is executed, the fab function returns an iteration value. During 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.

You can also manually call the next () method of fab (5) (because fab (5) is a generator object and this object has the next () method ), in this way, we can see the fab execution process more clearly:

>>> f = fab(5) >>> f.next() >>> f.next() >>> f.next() >>> f.next() >>> f.next() >>> f.next() Traceback (most recent call last):  File "<stdin>", line 1, in <module> StopIteration
View Code

 

When the function execution ends, generator automatically throws a StopIteration exception, indicating that the iteration is complete. In a for loop, the loop ends normally without handling the StopIteration exception.

 

6. How can I determine whether a function is a special generator function? You can use isgeneratorfunction to determine:

>>> from inspect import isgeneratorfunction >>> isgeneratorfunction(fab) True

 

7. note that fab and fab (5) are distinguished. fab is a generator function, and fab (5) is a generator returned by calling fab, like the difference between class definition and class instance:

>>> import types >>> isinstance(fab, types.GeneratorType) False >>> isinstance(fab(5), types.GeneratorType) True

Fab cannot be iterated, While fab (5) can be iterated:

>>> from collections import Iterable >>> isinstance(fab, Iterable) False >>> isinstance(fab(5), Iterable) True

Each time you call the fab function, a new generator instance is generated, and each instance has no influence on each other:

>>> f1 = fab(3) >>> f2 = fab(5) >>> print 'f1:', f1.next() f1: 1 >>> print 'f2:', f2.next() f2: 1 >>> print 'f1:', f1.next() f1: 1 >>> print 'f2:', f2.next() f2: 1 >>> print 'f1:', f1.next() f1: 2 >>> print 'f2:', f2.next() f2: 2 >>> print 'f2:', f2.next() f2: 3 >>> print 'f2:', f2.next() f2: 5
View Code

 

Function of return

In a generator function, if there is no return, it is executed until the function is complete by default. If return is executed, the StopIteration is directly thrown to terminate the iteration.

Another example

Another yield example is from File Reading. If you call the read () method directly on a file object, unpredictable memory usage may occur. A good way is to use a fixed-length buffer to constantly read the file content. With yield, you can easily read files without having to write iteration classes for reading files:

def read_file(fpath):    BLOCK_SIZE = 1024    with open(fpath, 'rb') as f:        while True:            block = f.read(BLOCK_SIZE)            if block:                yield block            else:                return

The preceding section briefly introduces the basic concepts and usage of yield. yield has more powerful usage in Python 3.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.