Functional programming python: Python usage preliminary analytical function of yield

This article describes the Python function of yield, yield is a function generator in a commonly used functions, from The developer documentation translation of IBM's official website, under the reference can be a friend in need
, you may have heard, with the function is called a yield in Python generator (generator), what generator?

Let's put aside the generator, with a common programming topics to show the concept of yield.

How to generate Fibonacci number

Fibonacci (the Fibonacci) is a very simple series of recurrent sequence, except for the first and second number, any number can be obtained by the first two numbers together. Output computer program Fibonacci number of first N Fibonacci number sequence is a very simple question that many beginners can easily write the following function:

Listing 1. Simple output the Fibonacci number of columns of the first N

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

Execution fab (5), we get the following output:

>>> fab(5)
1
1
2
3
5

The results no problem, but experienced developers will point out, direct digital printing with print function causes the reusability of poor function in the fab, fab because the function returns None, other functions can not get the number of columns in the generated function.

To improve the reusability fab functions, it is best not to directly print out the number of columns, but returns a List. The following is a function of rewrite after the fab second version:

Listing 2. Output Fibonacci number column before the second edition of 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

List fab can print out the function returns the following ways:

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

The rewritten fab functions return List reuse to meet the requirements, but the more experienced developers will point out that the function occupied in the operation of the memory will increase with the increase of parameters max, if you want to control memory occupation, it is best not to use List

To save intermediate results, but to iterate through iterable object. For example, in Python2.x, the code:
Listing 3. iterating through the iterable objects

 for i in range(1000): pass

It causes an element of the 1000 List, and the code:

for i in xrange(1000): pass

List is not generated a 1000 element, but to return the next value in each iteration, it takes up very little memory space. Because xrange not return List, but returns an iterable object.

Fab utilization iterable we can rewrite the function of a support iterable class, the following is the third version of the Fab:
Listing 4. The 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()

Fab class by next () returns the next number of the continuous series of memory usage is always constant:

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

However, the use of this class rewritten version of the code is far from the first edition fab function is more concise. If we want to keep the simplicity of the first edition fab functions, while also obtain the effect of iterable, the yield comes in handy:
Listing 5. yield Fourth Edition

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 the fab and compared to the first edition, only the print b changed to yield b, while maintaining simplicity in the iterable of the results obtained.

Call the fourth edition of the second edition of fab fab and exactly the same:

>>> for n in fab(5):
...  print n
...

Simply put, yield a function of the role is to become a generator, with a yield function is no longer an ordinary function, Python interpreter will treat it as a generator, call the fab (5) does not perform fab functions, but a return iterable objects! When the loop is executed for each loop are executed inside the fab the function code, when executed to yield b, fab function returns a value of the iteration, the next iteration, the code continues execution of the next statement yield b, and a function of local variables and the last look before the break execution is exactly the same, so the function continues to execute until the yield again.

You can also call fab (5) of the next hand () method (because the fab (5) is a generator object that has a next () method), so that we can more clearly see the implementation of the fab process:

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 is executed, generator automatically raise StopIteration, that the iteration is complete. In the for loop, without treatment StopIteration abnormal, normal cycle will end.

We can draw the following conclusions:

Yield is a function with a generator, and it is different from an ordinary function to generate a generator that looks like a function call, but does not perform any function code until it calls the next () (in the for loop will automatically call the next ( )) was started. Although the process execution process based upon the function of the execution, but each execution to a yield statement breaks out and returns a value iteration, the next execution of the next statement from the yield to continue. Looks like a yield function was interrupted several times in the course of normal execution, each interruption will yield returns the current iteration values.

Yield advantage is obvious, a function to rewrite a generator gained the ability iteration, the value of a next () lower than the state saved with the instance of the class to calculate not only the code simple, but the implementation process very clear.

How to determine whether a function is a special function generator? Analyzing isgeneratorfunction may be utilized:

Listing 7. Using isgeneratorfunction judge

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

And to distinguish between fab fab (. 5), fab is a generator function, and fab (. 5) calls a return Generator fab, such definitions and examples of the difference between the class and:

Examples of class definition and class Listing 8.

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

fab is not iterative, and fab (5) is iterative:

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

Each call fab function will generate a new generator instances, each instance independently of 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

return action

In a generator function, if there is no return, the default function to perform is completed, if the return in the implementation process, directly thrown StopIteration terminate iteration.

another example

Another example comes from the yield of the file read. If you call read directly on the file objects () method, it will lead to unpredictable memory footprint. Good method is to use a fixed-length buffer to continuously read the contents of the file. By yield, we no longer need to write iterator class to read the file, you can easily file reads:

9. Another example of yield Listing

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, yield, we will discuss in a future article in Python 3 there are more powerful uses.

Note: The code in this article are in Python 2.7 debugging through

Finally, we recommend a very wide python learning resource gathering, [click to enter] , here are my collection before learning experience, study notes, there is a chance of business experience, and calmed down to zero on the basis of information to project combat , we can at the bottom, leave a message, do not know to put forward, we will study together progress

Published 44 original articles · won praise 56 · views 60000 +

Guess you like

Origin blog.csdn.net/haoxun10/article/details/104908622