Brief introduction and application of Python generator function yield

Source: Internet
Author: User
Tags generator iterable in python


Python yield Introduction






What is a generator function?

A generator function is a function that remembers where the last function returned, and saves some states of the function at that time, such as variables, objects in the function field, and so on, which can then be executed the next time the function is executed.

The builder owns the next method and behaves exactly like an iterator, which means that the generator can also be used in a python for loop. In addition, the special syntax support for generators makes it much simpler to write a generator than to customize a regular iterator, so the generator is one of the most common features.

To implement the generator, we can use the yield function to return the data to achieve the goal.

A simple example:

Like writing a function that asks for Fibonacci, we can write this:


def fib (max):
A, B = 1, 1 while
a < max:
yield a
, B = B, a+bfor N in fib:
print N



Run Result:

1
1
2
3
5
8
13

We can look at it in a different way, for example, if we change the execution code like this:


A = fib
print type (a) for I in
Range (5):
print A.next ()



You can see that the result of type (a) is <type ' generator ', stating that the type of a is a generator, and that each execution of a.next () outputs a value of the result.

Using yield, the benefit of the generator function is that, for example, we're going to read a very large amount of data, and using a normal function will read all the data into memory at once. The generator function only reads and processes once at a time, and can improve efficiency and save space.



Analysis of the use of Python yield






Beginners Python developers often find many Python functions using the yield keyword, however, with yield function execution process is not the same as the normal function, yield in the end what to do, why to design yield? This article will explain the concept and usage of yield to help readers realize the simple and powerful functions of yield in Python.

As you may have heard, functions with yield are called generator (generators) in Python, what is generator?

Let's throw away the generator and show the concept of yield with a common programming topic.






How to generate Fibonacci? Pirate? / Strong>

Fibonacci (Fibonacci)? Pirates and 桓 龇 桓 龇 虻 サ 虻 サ Look at the N number of stolen weapons is a very simple problem. Many beginners can easily write the following functions:



Listing 1. Simple output of Fibonacci? Number of Pirate Stars N






Listing 1. Simple output Fibonacci? Number of stolen stars N


Def FAB (max):
N, a, b = 0, 0, 1 while
n < max:
print B
A, B = B, a + bn = n + 1




Executive Fab (5), we can get the following output:


>>> Fab (5)
1
1
2
3
5



The results are fine, but experienced developers will point out that printing numbers directly in the FAB function can cause the function to be less reusable because the FAB function returns None, and other functions cannot get the sequence that the function generates.

To improve the reusability of the Fab function, it is best not to print the columns directly, but to return to a List. The following is the second version of the FAB function rewrite:






Listing 2. Output Fibonacci? The second edition of the number of stolen stars N


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
L




You can print out the List returned by the FAB function by using the following methods:


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



The rewritten fab function satisfies the need for reusability by returning a list, but more experienced developers will note that the memory consumed by the function increases as the parameter max increases, and if you want to control the memory footprint, it is best not to use the list

To save the intermediate results instead of iterating through the Iterable object. For example, in python2.x, the code:






Listing 3. Iterate through the Iterable object

For I in range (1000): Pass

Causes a List of 1000 elements to be generated, and the code:

For I in xrange (1000): Pass

A List of 1000 elements is not generated, but the next value is returned in each iteration, with little memory space. Because Xrange does not return the List, it returns a Iterable object.

Using iterable we can rewrite the FAB function as a class that supports iterable, and the following is the third version of Fab:






Listing 4. Third version


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



The Fab class continuously returns the next number of the series through Next (), and the memory footprint is always constant:





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




However, with this version of class rewriting, the code is far less concise than the first version of the Fab function. If we want to maintain the simplicity of the first version of the FAB function and get the iterable effect, yield comes in handy:
Listing 5. Using the fourth edition of 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

'''

The fourth version of Fab and the first edition, only to change print B to yield B, while keeping the simplicity of the same time to obtain the iterable effect.

The fourth version of Fab and the second version of Fab are exactly the same:


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



Simply put, the function of yield is to make a generator, a function with yield is no longer a normal function, the Python interpreter treats it as a generator, the call FAB (5) does not execute the FAB function, but instead returns a Iterab Le Object! When the For loop executes, each loop executes the code inside the FAB function, when executed to yield B, the FAB function returns an iteration value, and the next iteration, the code continues from the next statement in yield B, and the function's local variable looks exactly the same as before the last interrupt execution, so the function Continue execution until you meet yield again.

You can also manually invoke the next () method of the Fab (5) (Because Fab (5) is a generator object that has the next () method) so that we can see the fab execution process more clearly:






Listing 6. Execution process


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




When the function completes, the generator automatically throws the Stopiteration exception, which indicates that the iteration is complete. In the For loop, the loop ends normally without handling the stopiteration exception.

We can draw the following conclusions:

A function with yield is a generator, unlike a normal function, which generates a generator that looks like a function call, but does not execute any function code until it is called next (), which is automatically called next () in the For loop, to begin execution. Although the execution process is still executed as a function's process, each execution to a yield statement is interrupted and an iteration value is returned, and the next execution is performed from the next statement of yield. It looks as if a function was interrupted several times by yield during normal execution, with each interrupt returning the current iteration value through yield.

The benefit of yield is obvious: rewriting a function as a generator gives you the ability to iterate over the value of the next next () rather than the instance save state of the class, not only the code is concise, but the execution process is unusually clear.

How can I tell if a function is a special generator function? You can use Isgeneratorfunction to judge:






Listing 7. Use Isgeneratorfunction to judge


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



Be aware of the distinction between Fab and fab (5), Fab is a generator function, and fab (5) is the invocation of a generator returned by FAB, like the definition of a class and the difference between instances of a class:






Listing 8. The definition of the class and an instance of the class


>>> Import Types
>>> isinstance (fab, types. Generatortype)
False
>>> isinstance (Fab (5), types. Generatortype)
True



Fab can not be iterated, and Fab (5) is iterative:


>>> from collections import iterable
>>> isinstance (Fab, iterable)
False
>>&G T Isinstance (Fab (5), iterable)
True



Each time the FAB function is invoked, a new generator instance is generated, with each instance having no effect:


>>> f1 = Fab (3)
>>> F2 = Fab (5)
>>> print ' F1: ', F1.next ()
f1:1
>&G t;> 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.N Ext ()
f2:2
>>> print ' F2: ', F2.next ()
f2:3
>>> print ' F2: ', F2.next ()F2:5




return action

in a generator function, if there is no return, the default execution to the function is complete, if during execution Return, the stopiteration is thrown directly to terminate the iteration.

Another example

Another example of yield comes from file reads. If you call the Read () method directly on a file object, it can cause unpredictable memory consumption. A good approach is to use a fixed-length buffer to continuously read the contents of the file. With yield, we no longer need to write an iterative class for reading files, so we can easily implement file reads:
Listing 9. Another yield example


def read_file (Fpath):
block_size = 1024
with open (Fpath, ' RB ') as F: While
True:
block = F.read (block_size)
if blocks:
yield block
else:
Return



The above is just a brief introduction to the basic concepts and usage of yield, and yield has a stronger use in Python 3, which we'll discuss in subsequent articles.

Note: The code in this article is debugged in Python 2.7 through


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.