Python-Functional Programming builder

Source: Internet
Author: User

In the previous learning process, we know that iterators have two benefits:

一是不依赖索引的统一的迭代方法二是惰性计算,节省内存

But Iterators also have their own significant drawbacks, which is

不如按照索引取值方便 一次性,只能向后取值,不能向前取值

So we also need to learn another object that has生成器

1. What is a generator

If a function body contains the yield keyword, the function is a generator function that executes the function to get a generator object

2. Get generator

First look at the following code

def foo():    print("first...")    yield    print("second...")    yield    print("third...")g=foo()print(g)

Based on the definition of the generator above: The 函数体内部包含yield关键字,则该函数就是生成器函数 result of the above function execution is a generator object

Execute the above code to see the results of the program execution

<generator object foo at 0x0000000001DF2BF8>

Can be seen:上面的函数执行的结果g就是一个生成器对象,上面的函数foo就是一个生成器函数

3. Built-in methods for generators

Modify the code above and call the Dir method to see the methods contained in the builder

def foo():    print("first...")    yield    print("second...")    yield    print("third...")g=foo()print(dir(g))

Print the method inside the generator, you can see the results of the printing

[‘__class__‘, ‘__del__‘, ‘__delattr__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__init_subclass__‘, ‘__iter__‘, ‘__le__‘, ‘__lt__‘, ‘__name__‘, ‘__ne__‘, ‘__new__‘, ‘__next__‘, ‘__qualname__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘close‘, ‘gi_code‘, ‘gi_frame‘, ‘gi_running‘, ‘gi_yieldfrom‘, ‘send‘, ‘throw‘]

In these results, it can be seen __iter__方法 that there are and __next__方法 , thus can be judged生成器的本质就是迭代器
生成器是迭代器的一种

4. Determine if the generator is an iterator

Modify the above code

def foo():    print("first...")    yield    print("second...")    yield    print("third...")g=foo()from collections import Iterableprint(isinstance(g,Iterable))

View Print Results

True

The above two examples can prove that:生成器的本质是迭代器,生成器就是迭代器的一种

5. The generator's __iter__方法And __next__方法

Since the essence of the generator is an iterator, __iter__方法 __next__方法 What will be the result of invoking the generator's and

Modify the above code

def foo():    print("first...")    yield    print("second...")    yield    print("third...")g=foo()print(g)print(g.__iter__())g.__next__()

Program execution Results

<generator object foo at 0x0000000001DF2BF8><generator object foo at 0x0000000001DF2BF8>first...

From the above program execution results can be seen:直接打印生成器g和调用生成器g.__iter__方法,得到的结果都是生成器对象g 在内存中的地址

The calling method, in effect, takes a value out of the g.__next__ generator G, executes the g.__next__ method once, and triggers the generator's value operation, which is shown in the code above as the down-execution of the Foo function

As you can see from the execution results of the above program, only the first print function of the Foo function is executed, and the second and third print functions are not executed.

通常对函数来说,函数开始执行以后直到return语句,函数才会停止执行

Once the method is executed here g.__next__ , the Foo function executes a line of code, and the yield is stopped, where yield seems to play the role of return.

实际上,yield关键字的功能之一就是起到返回的作用

The above program execution encountered yield, this g.__next__ method is completed.

在函数的执行过程中,如果函数的return语句有返回值,则函数的执行完成就得到return语句的返回值,如果return没有定义返回值或者函数中没有定义return语句,则函数的执行结果默认为None

Modify the above code to print the __next__ execution result of the method

def foo():    print("first...")    yield    print("second...")    yield    print("third...")g=foo()print(g.__next__())

Program execution Results

first...None

As you can see, when the method is called, no __next__ arguments are received after yield,yield默认的返回值也是None

6.yield followed by return value

So what happens to the program execution if you take a return value after the yield keyword?
Modify the above code, followed by a return value after the yield keyword, to see the execution results of the program

def foo():    print("first...")    yield 1    print("second...")    yield 2    print("third...")g=foo()print(g.__next__())

Program execution Results

first...1

As can be seen from the execution results of the above program, yield will return the number of subsequent calls, as __next__ the result of the method execution

The difference between 7.yield and return

In a function, no matter how many return statements are defined in a function, the function is aborted when it executes to the first return statement, and the statements following it will not be executed again.

For yield, each time the method is called, the __next__ program executes from the start down until the yield statement is encountered, and the program pauses until the second call __next__ method, where the program resumes execution from the last pause until it encounters the next yield or the program executes

在上面的例子里,是使用yield把函数foo变成一个生成器,执行foo函数时,并不会立即执行foo函数,而是先得到生成器g,当调用一次`g.__next__`方法时,函数foo开始向下执行,遇到yield时,程序暂停,当下一次调用`g.__next__`方法时,函数foo继续从上一次暂停的地方开始向下执行,直到遇到yield暂停
8. Stopiteration of the generator

Modify the program, call the method multiple times __next__ to see the execution results of the program

def foo():    print("first...")    yield    print("second...")    yield    print("third...")g=foo()print(g)print(g.__iter__())g.__next__()print(‘*‘*30)g.__next__()print(‘#‘*30)g.__next__()

Program execution Results

<generator object foo at 0x0000000001DF2BF8><generator object foo at 0x0000000001DF2BF8>first...******************************second...##############################third...Traceback (most recent call last):  File "E:/py_code/test.py", line 28, in <module>    g.__next__()StopIteration

As you can see from the execution of the above program, each time a generator is called, __next__ a return value is obtained, which is equivalent to taking a value from the iterator.

If the program does not get the return value during execution, it means that the last value of the iterator has been traversed, so the method is called again __next__ , and the program throws an exception

9. For loop traversal of the generator

In the previous study already knew, 生成器本质上就是一个迭代器 . Since it is an iterator, of course, you can use the For loop to traverse the generator

Modify the example above and use the For loop to traverse the generator

def foo():    print("first...")    yield 1    print("second...")    yield 2    print("third...")g=foo()for i in g:    print(i)    print("*"*30)

To view the execution results of a program

first...1******************************second...2******************************third...

In the example above, each execution of a for loop is equivalent to executing the method once, and yield returns the number after which it was followed g.__next__ , so the first two execution results for the For loop are the print function and the number of yield followed

The For loop executes to the third time, executes the print function, the program throws StopIteration an exception, but StopIteration the exception is caught by the for loop, so the For loop executes the third time only the print statement is executed

10. Summary:

The yield keyword features:

与return的功能类似,都可以返回值,但不一样的地方在于一个函数中可以多次调用yield来返回值为函数封装好了`__iter__方法`和`__next__方法`,把函数的执行结果变成了迭代器`遵循迭代器的取值方式(obj.__next__())`,触发的函数的执行,函数暂停与再继续都由yield保存
11. Example: Using yield to simulate a command in Linux: Tail-f | grep ' ERROR ' | grep ' 404 '

The code is as follows:

import timedef tail(file_path, encoding=‘utf-8‘):    with open(file_path, encoding=encoding) as f:        f.seek(0, 2)        while True:            line = f.readline()            if line:                yield line            else:                time.sleep(0.5)def grep(lines, pattern):    for line in lines:        if pattern in line:            yield lineg1 = tail(‘a.txt‘)g2 = grep(g1, ‘error‘)g3 = grep(g2, ‘404‘)for i in g3:    print(i)

Python-Functional Programming builder

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.