Python starter (eight) iterator and generator

Source: Internet
Author: User
Tags function definition iterable

Iterators and generators 1, list-generated

List Generation List Comprehensions is a built-in, Python very simple but powerful build that you can use to create list .
For example, to generate list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] can be used list(range(1, 11)) :

>>> list(range(1, 11))[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

But what if you want to build [1x1, 2x2, 3x3, ..., 10x10] ? Method One is the loop:

>>> L = []`>>> for x in range(1, 11):...    L.append(x * x)...>>> L[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

But the loop is too cumbersome, and the list generation can use a line of statements instead of loops to generate the above list :

>>> [x * x for x in range(1, 11)][1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

When writing list generation, put the elements to be generated in x * x front, followed by the for loop, you can list create, very useful, write a few more times, you will soon be familiar with this syntax.

for循环It can be added later if判断 , so we can filter out only the even squares:

>>> [x * x for x in range(1, 11) if x % 2 == 0][4, 16, 36, 64, 100]

小结:
The use of list generation, can be generated quickly list , can be deduced from one list another list , and the code is very concise.

2. Generator

???? With list generation, we can create a list directly. However, with memory limitations, the list capacity is certainly limited. Also, creating a list of 1 million elements takes up a lot of storage space, and if we just need to access the first few elements, the vast majority of the space behind it is wasted.

???? So, if the list element can be calculated according to an algorithm, can we continue to calculate the subsequent elements in the process of the loop? This eliminates the need to create a complete list, which saves a lot of space.在Python中,这种一边循环一边计算的机制,称为生成器:generator。

There are a number of ways to create one generator . The first method is simple, as long as a list of the generated formula is [] changed () to create a generator :

&gt;&gt; L = [x * x for x in range(10)]&gt;&gt; L[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]&gt;&gt; g = (x * x for x in range(10))&gt;&gt; g<generator object &lt;genexpr&gt; at 0x1022ef630&gt;

The L difference between creating and making is g only the outermost []和() , the one, and the L list other g generator .

We can print out list every element directly, but how do we print out generato every element of R?

If you want to print out one, you can next() get generator the next return value from the function:

&gt;&gt; next(g)0&gt;&gt; next(g)1&gt;&gt; next(g)4&gt;&gt; next(g)9&gt;&gt; next(g)16&gt;&gt; next(g)25&gt;&gt; next(g)36&gt;&gt; next(g)49&gt;&gt; next(g)64&gt;&gt; next(g)81&gt;&gt; next(g)Traceback (most recent call last):File "&lt;stdin&gt;", line 1, in &lt;module&gt;StopIteration

From the front we know a concept: generator save the algorithm, each call next(g) , calculate g The value of the next element, until the last element is computed, no more elements when the error is thrown StopIteration .

Of course, this constant invocation is next(g) really too perverted, the correct way is to use for循环 , because it is generator also an iterative object:

&gt;&gt; g = (x * x for x in range(10))&gt;&gt; for n in g:...     print(n)... 0149162536496481

So, we create a generator post that basically never calls next() , but for循环 iterate through it and don't need to be concerned about StopIteration the error.

generatorVery powerful. If the calculated algorithm is more complex, and the loop with similar list generation for cannot be implemented, it can also be implemented with functions.

For example, the famous Fibonacci sequence, in (Fibonacci) addition to the first and second numbers, can be added by the first two numbers in any number:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

The Fibonacci sequence is not written in a list, but it is easy to print it out with a function:

def fib(max):    n, a, b = 0, 0, 1    while n < max:        print(b)        a, b = b, a + b        n = n + 1    return ‘done‘注意,赋值语句:    a, b = b, a + b相当于:    t = (b, a + b) # t是一个tuple    a = t[0]    b = t[1]但不必显式写出临时变量t就可以赋值。上面的函数可以输出斐波那契数列的前N个数:>>> fib(10)11235813213455done

Careful observation, it can be seen, fib函数 is actually defined by the Fibonacci sequence of the calculation rules, you can start from the first element, the subsequent arbitrary elements, this logic is actually very similar generator .

That is, the above function and generator only one step away. To turn fib函数 generator it into, just need to print(b) change to yield b be able to:

This is generator another way of defining it. If a function definition contains a yield keyword, then the function is no longer a normal function, but a generator :

def fib(max):    n,a,b = 0,0,1    while n < max:        #print(b)        yield  b        a,b = b,a+b        n += 1    return "done"print(fib(6))f = fib(6)print(f.__next__())print(f.__next__())print(f.__next__())执行结果:D:\Python18\venv\Scripts\python.exe D:/Python18/day04/斐波那契数列.py<generator object fib at 0x0000000000BCB3B8>112

Breakpoint Analysis:
(1) defines the fib function with the incoming parameter max ;
(2) Incoming fib (6) . 6 Generate a generator as a parameter and assign a value to f , you can view the memory address of the generator through print (FIB (6)) ;
(3) print (f.__next__ () The first value of the generator is taken out, and the fib function is called directly;
(4) Initial value n=0, a=0, B=1 , judging n&lt;6 Execute Yield b saves the interrupt state of the function and returns the value of b . print (f.__next__ () Executes the result 1 ;
(5) Executes print (f.__next__ () to take the second value, which jumps back yield b , which returns the state that was saved when the function was interrupted, and then executes A, B = b,a+b , at which time a=b, or a=1;b=a+b, B=1 .
(6) Execute n + = 1 , n value plus 1 , then return to while loop judgment;
(7) Judging 1 &lt; 6 , continue yield b . continues to save the function break state and returns the value of b . The result of print (f.__next__ () is 1 ;
(8) The same, then the third print (f.__next__ () takes out the third value, The execution result is 2 . Thus the final direct result is printed as:
1<br/>1<br/>2

What is most difficult to understand here is that it is generator not the same as the execution process of a function. 函数是顺序执行, return语句 or the last line of the function statement 返回 . Instead, it generator的函数 executes at each invocation, next() encounters yield语句返回 , and executes again from 上次返回的yield语句处继续执行 .

In fib The example above, we continue to call during the loop yield , and we are constantly interrupted. Of course, you have to set a condition for the loop to exit the loop, or it will produce an infinite sequence.

Similarly, after changing a function generator , we basically never use it to next() get the next return value, but instead use it directly for循环 to iterate:

def fib(max):    n,a,b = 0,0,1    while n < max:        #print(b)        yield  b        a,b = b,a+b        n += 1    return "done"for n in fib(6):    print(n)执行结果:112358

But for循环 generator when you call, you find the statement that you can't get generator return 返回值 . If you want to get the return value, the 必须捕获StopIteration错误 return value is contained in StopIteration value :

def fib(max):    n,a,b = 0,0,1    while n < max:        #print(b)        yield  b        a,b = b,a+b        n += 1    return "done"f = fib(6)while True:   try:       x = next(f)       print(x)   except StopIteration as e:       print(‘Generator return value:‘, e.value)       break执行结果:f: 1f: 1f: 2f: 3f: 5f: 8Generator return value: done

You can also achieve yield the effect of concurrency in a single-threaded scenario: The following execution is equivalent to achieving concurrency in the serial process and also as a co-operation.

#!/usr/bin/python# _*_ coding:utf-8 _*_# Aothr: Kimimport timedef consumer(name):    print("%s 准备吃包子啦!" %name)    while True:       baozi = yield       print("包子[%s]来了,被[%s]吃了!" %(baozi,name))def producer(name):    c = consumer(‘A‘)    #生成一个c的生成器    c2 = consumer(‘B‘)   #生成一个c2的生成器    c.__next__()        #执行producer()时,会直接调用到consumer,然后打印A 准备吃包子啦!到了yield直接中断    c2.__next__()       #同上,打印B 准备吃包子啦!    print("老子开始准备做包子啦!")    for i in range(3):    #循环0~2的序列        time.sleep(1)        print("做了2个包子!")        c.send(i)           #此时使用send将i的值发送给yield,继续执行 print("包子[%s]来了,被[%s]吃了!" %(baozi,name)),执行结果为:包子[0]来了,被[A]吃了!while True死循环又到了yield,中断函数。执行下一步。        c2.send(i)   #同上,执行结果为:包子[0]来了,被[B]吃了!至此i=0执行完毕,继续下一个i=1的循环。producer("alex")执行结果:A 准备吃包子啦!B 准备吃包子啦!老子开始准备做包子啦!做了2个包子!包子[0]来了,被[A]吃了!包子[0]来了,被[B]吃了!做了2个包子!包子[1]来了,被[A]吃了!包子[1]来了,被[B]吃了!做了2个包子!包子[2]来了,被[A]吃了!包子[2]来了,被[B]吃了!
3. iterators

A class is a collection of data types, such as list、tuple、dict、set、str ;

One type is generator , including generators and bands yield generator function .

These can be 直接 applied to a system for循环的对象 called an iterative object: Iterable .

You can use to isinstance() determine whether an object is an Iterable object:

>>> from collections import Iterable>>> isinstance([], Iterable)True>>> isinstance({}, Iterable)True>>> isinstance(‘abc‘, Iterable)True>>> isinstance((x for x in range(10)), Iterable)True>>> isinstance(100, Iterable)False

The generator can be used not only for循环 , it can also be next()函数 called continuously and return the next value until the last throw StopIteration error indicates that the next value cannot continue to be returned.

next()函数the object that can be called and constantly returns the next value is called 迭代器:Iterator .

You can use to isinstance() determine whether an object is an Iterator object:

>>> from collections import Iterator>>> isinstance((x for x in range(10)), Iterator)True>>> isinstance([], Iterator)False>>> isinstance({}, Iterator)False>>> isinstance(‘abc‘, Iterator)False

Generators are Iterator objects, but list、dict、str although Iterable they are, they are not Iterator .

Turn the list、dict、str wait Iterable into a Iterator function you can use iter() :

>>> isinstance(iter([]), Iterator)True>>> isinstance(iter(‘abc‘), Iterator)True

You might ask, why is the data type list, dict, str , etc. not Iterator ?

This is because the Iterator object for Python represents a data flow, and the Iterator object can be next () The function calls and returns the next data continuously until the stopiteration error is thrown without data. You can think of this data stream as an ordered sequence, but we can't know the length of the sequence in advance, but we will only continue to calculate the next data on demand through the next () function, so the calculation of Iterator is inert, It is calculated only if you need to return the next data.

Iterator can even represent an infinitely large stream of data, such as the whole natural number. Using list is never possible to store the entire natural number.

Summary
Any object that can be used for the for Loop is iterable type ;

Any object that can act on the next () function is Iterator types, which represent a sequence of lazy computations,

Collection data types such as list, dict, str , and so on are iterable but not Iterator , but you can get a Iterator object through the ITER () function . for Loop for

Python is essentially implemented by calling the next () function , for example:

for x in range(5):    print(x)实际上完全等价于:# 首先获得Iterator对象:it = iter([0,1, 2, 3, 4])# 循环:while True:    try:        # 获得下一个值:        x = next(it)    except StopIteration:        # 遇到StopIteration就退出循环        break

Python starter (eight) iterator and generator

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.