Analysis of the use of Python yield

Source: Internet
Author: User
Tags execution generator iterable stdin in python

This article mainly introduces the use of Python yield, this article gives a number of examples to analyze the use of yield, the need for friends can refer to the

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 yield Read and use to help readers understand the simple and powerful features of Python yield.

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 numbers

Fibonacci (Fibonacci) is a very simple recursive sequence in which any number can be added together with the first two numbers, except for the number one and the second. It is a very simple question to output the first N number of Fibonacci columns with a computer program, and many beginners can easily write the following functions:

Listing 1. Simple output Fibonacci Number column N

The code is as follows:

Def FAB (max):

N, a, b = 0, 0, 1

While n < max:

Print B

A, B = B, A + b

n = n + 1

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

The code is as follows:

>>> 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 Number List N Second Edition

The code is 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 L

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

The code is as follows:

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

The code is as follows:

For I in range (1000): Pass

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

The code is as follows:

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

The code is as follows:

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:

The code is as follows:

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

The code is as follows:

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:

The code is as follows:

>>> 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 will executing the code inside the FAB function, when executing to yield B, the FAB function returns an iteration value, and at the next iteration, the code continues from the next statement in yield B, and the local variable of the function looks exactly the same as before the last interrupt execution. , so the function continues to execute until it encounters 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

The code is as follows:

>>> 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 " ", line 1, in

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 do you determine if a function is a special generator function? You can use Isgeneratorfunction to judge:

Listing 7. Use Isgeneratorfunction to judge

The code is as follows:

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

The code is as follows:

>>> Import Types

>>> isinstance (fab, types. Generatortype)

False

>>> isinstance (Fab (5), types. Generatortype)

True

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

The code is as follows:

>>> from collections Import iterable

>>> isinstance (Fab, iterable)

False

>>> isinstance (Fab (5), iterable)

True

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

The code is as follows:

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

The role of Return

In a generator function, if there is no return, the default is performed to the function, and if return is performed during execution, throw stopiteration to terminate the iteration directly.

Another example

Another example of yield comes from file reading. 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 of read files, so that file reads can be easily achieved:

Listing 9. Another example of yield

The code is as follows:

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

Related Article

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.