1

Python generator之奇妙!

 3 years ago
source link: https://zhuanlan.zhihu.com/p/393064633
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Python generator之奇妙!

4.4k收藏,CrackingOysters,也是微信公众号

之前有人跟我说,觉得Python的generator好难理解。给TA讲了一下,TA似乎豁然开朗了。

最近这两天用Python写了个爬虫,代码在GitHub - Celthi/ScienceNetool (后面会写文章总结一下爬虫的写法和思路),一直既往惊叹于generator的美,惊叹于建立在简简单单地语法上的奇妙!所以再聊聊generator——

Generator

Python 的generator的引入是在2001 https://www.python.org/dev/peps/pep-0255/,比如下面的代码创建一个简单的generator,这个generator,会生成所有的自然数——是不是很厉害?

def natural_number():
    i = 0
    while True:
        yield i
        i += 1

新手看到这个代码,可能会害怕。其实理解它很简单,让我们先看看它是常见的使用的方法

n =  natural_number()
for i in n:
    print(i)

for in 遍历所有的自然数,然后打印出来。简单吧!(注意这个代码是个死循环,仅为了示意)

所以generator,当你调用它的时候,它里面的代码不会运行,会返回一个generator object。

然后你就可以对这个generator object,做任何可以对它做的事情,如遍历,或者返回给其他调用者。

当你将next方法作用于它时,就会恢复运行,获取下一个yield的值。一直到运行结束,返回StopIteration exception.

下面的代码测试你的理解程度

def f():
    yield 5

n = f()
print(n) 
print(next(n)) 
print(next(n))

上面的代码会输出什么?

def f():
    yield 5
    print('end')

n = f()
print(n) 
print(next(n)) 
print(next(n))

上面的代码会输出什么?

def f():
    yield 5
    print('end')
for i in f():
    print(i)

generator的优点

上面的例子,我们可以看到,generator占用的内容比单纯的list会节省很多内存。

因为如果用list存放所有的自然数,显然是不可能的,我们没有这么大的计算机,世界上也永远不可能出现。

而generator 只花了一点内存,就可以产生所有的自然数。如果你不信,你把上面的程序跑一下,然后一直等到宇宙的尽头。

化整为零,以有限表示无限

自然数是无穷的,但是却可以用generator生成。

generator其实是协程的一种,所以generator可以暂停,然后再恰当的时候再恢复运行。

可以参考我之前关于协程的文章,Coroutine, 异步,同步,async, await

所以generator可以让你实现控制流的切分和重组,从而贴近实际的编程模型。

https://www.python.org/dev/peps/pep-0255/

Coroutine, 异步,同步,async, await


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK