Python Iterator and Generator

Python Iterator and Generator

Iterator

Iterator (Iterator) and iterables (Iterable) tend to be binding. Iterables is what we usually use often list, string, tuplethat. In fact the concept of iterator iteration will be much broader than the subject, a few examples will be able to understand.

In use list, when this type of data, we often use the following iterative this way:

# eg 1
mylist = [1,2,3,4]
for x in mylist:
    print(x)
>>>1
>>>2
>>>3
>>>4

Sometimes very strange for cycle Why use something, the index list will be automatically turned back one by one, walked at the end, and will automatically stop, will not have list out of rangethe error. magical. In fact, for circulation to do more than that simple. To illustrate this problem, you must first say iterator specifically how to do, what it is.

To create an iterator, it is necessary to implement two methods, respectively __iter__(), and __next__(), as well as implement exception mechanism StopIteration. Consider the following example:

# eg 2
class PowTwo:
    """Class to implement an iterator of powers of two"""

    def __init__(self, max = 0):
        self.max = max

    def __iter__(self):
        self.n = 0
        return self

    def __next__(self):
        if self.n <= self.max:
            result = 2 ** self.n
            self.n += 1
            return result
        else:
            raise StopIteration

We can see, the iterator by writing a class is defined, the class which implements just said __iter__()and __next__()methods. This iterator is used to generate a series of digital power exponent of 2, see the following specific usage:

a = PowTwo(4)
i = iter(a)         # attention please
next(i)
>>>1
next(i)
>>>2
next(i)
>>>4
next(i)
>>>8
next(i)
>>>16
next(i)
>>>Traceback (most recent call last):
    ...
    StopIteration

Carefully Kane, with the first line of code creates an instance of 4 a, set the upper limit of this iterator iteration, and then use this example not directly on it, we had to call the iter()function to the acompletely evolved into one Iterator, and then with the next next()shiny function debut. In fact, I also quite strange, the direct use of this type it out for example, the following code:

a = PowTwo(4)
a.__iter__()
a.__next__()
>>>1
a.__next__()
>>>2
a.__next__()
>>>4
a.__next__()
>>>8
a.__next__()
>>>16
next(i)
>>>Traceback (most recent call last):
    ...
    StopIteration

Not a problem, but you compare the two codes, which the United States no doubt. . . Besides, with the same decorator, all for the simple and beautiful thing is born.

OK, you can return to the original starting point --for cycle. The code in Example 1, for circulation in the end what has been done, the answer is, for the cycle in fact, is to first mylistbecome an iterator, then use a while loop to iterations:

iter_obj = iter(mylist)
while True:
    try:
        element = next(iter_obj)
    except StopIteration:
        break

Explain all the way over, it should not be difficult to understand the iterator. It boils down to this:

  1. How to have an iteration object, then the direct use of iter()the function to initialize it, then madness next()can;
  2. If there are no ready-made iterable, then write a class, the class which I remember achieve __iter__()and __next__()methods, as well as abnormal mechanism StopIteration, and then operating the same 1;
  3. If you want an infinite iterator, do not implement exception mechanism StopIterationcan be.



Generator

This stuff than the iterator more complex, so also score a few small points, one by one break.

1. The generator is valid

Builder also requires an iterative series of Python-oriented questions, common solution. Since there is an iterator, the iteration can solve many problems, but also for the wisdom that Le generator?

The main reason is the cost of iterators too. Fortunately for some small problems, big problems need to iterate the elements very large, the iterator will not make the awkward. Also, create an iterator, but also quite troublesome to tell the truth, look at the second point above a small sum, you have to implement these methods and manual handling exceptions.

Iterator class and write, in fact, a function can handle things, why so complicated. It should be this scene, the generator is engaged in the matter in the function object.

For this reason a superficial, first clear the generator, a naturally transparent. Look at a small example, to write a generator function (Generator Function):

# eg 1
def my_gen():
    n = 1
    print('This is printed first')
    yield n

    n += 1
    print('This is printed second')
    yield n

    n += 1
    print('This is printed at last')
    yield n

The above is a simple function generator, a keyword and more yield, look carefully will find that this function is not even return! Closer look at the code, yes, yieldreplaced return. That how to use it, there are two uses are as follows:

# usage 1
a = my_gen()
next(a)
>>>This is printed first
    1
next(a)
>>>This is printed second
    2
next(a)
>>>This is printed at last
    3
next(a)
>>>Traceback (most recent call last):
    ...
    StopIteration
# usage 2   
for item in my_gen():
    print(item) 
>>>
This is printed first
1
This is printed second
2
This is printed at last
3

For Usage 1, the functions assigned to the athen almost crazy next()to. You will find, as we did not achieve as iterators __iter__()and __next__()methods, as well as unusual mechanism StopIteration, but with a yieldkeyword, the function generator has reached the same iterator effect.

For use 2, more leather, and even without the assignment of the operation, directly for the generator function. . .

2. The loop mechanism generator

Just that little function, is one of the most common example, the problem is that if there are multiple n want to play, not that much to write how much manual? That of course, the cycle of play, with a circulation mechanism generator. The following is an example of a small reverse output:

# eg 2
def rev_str(my_str):
    length = len(my_str)
    for i in range(length - 1,-1,-1):
        yield my_str[i]

for char in rev_str("hello"):
     print(char)
>>>o
>>>l
>>>l
>>>e
>>>h

Yes, really boring, the program worthwhile reverse output on builder had it not worthwhile, but just wanted to give this concept of circular mechanism generator. If you find this rev_str()function and normal reverse function exactly the same, just returnreplaced yield, then all is well, to understand is this. Simple replacement operation on such a note, you get a builder, not a provincial thing is more than the iterator.

3. Generator expressions (Generator Expression)

Do not know if you have used the list generation type, not used it should also be seen, which is similar to an anonymous function syntax is simple, such as:

# eg 3
my_list = [1, 3, 6, 10]

[x**2 for x in my_list]
>>>[1, 9, 36, 100]

Generator expressions and this is almost the same, do not believe you can see:

# eg 4
my_list = [1, 3, 6, 10]

a = (x**2 for x in my_list)
next(a)
>>>1
next(a)
>>>9
next(a)
>>>36
next(a)
>>>100

The list of the formula []directly into (), there was obtained a generator.

4. Why Generator???

(1). Simple

Back to the example of that class beginning iterator, ye write it with a generator?

def PowTwoGen(max = 0):
    n = 0
    while n < max:
        yield 2 ** n
        n += 1

It is simple, then you can use this generator function of the travel.

(2) Overhead small

The same need to iterate a function, if written in a normal function, once the need to iterate the elements particularly, when in use, and other common functions require all elements calculated, and then the return value to you. Builder is not, and it calculates a time, when used to take one, and it will remember the location, at a next time calculation, so the cost of space is very small.

(3). Unlimited

Look at the following function:

def all_even():
    n = 0
    while True:
        yield n
        n += 2

Write a normal function, you can not necessarily write function, a generator can operate unlimited can. (Iterator also be, that is a little troublesome)

5. Give an example

# 利用yield生成一个斐波那契数列的生成器
def fib(max):               
    n,a,b=0,0,1
    while n<max:
        yield b
        a,b=b,a+b
        n+=1
    return 'done'   # 要不要这句话都行
f=fib(6)
next(f)             # 疯狂next()它
>>>
1
1
2
3
5
8
Traceback (most recent call last):
...
StopIteration: done

Guess you like

Origin www.cnblogs.com/machine-lyc/p/11332358.html