了解Python中的生成器 [英] Understanding generators in Python

查看:81
本文介绍了了解Python中的生成器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此刻,我正在阅读Python手册,目前正在查看生成器.我发现很难做出决定.

I am reading the Python cookbook at the moment and am currently looking at generators. I'm finding it hard to get my head round.

当我来自Java背景时,是否有Java等效语言?这本书讲的是生产者/消费者",但是当我听到我想到线程化的时候.

As I come from a Java background, is there a Java equivalent? The book was speaking about 'Producer / Consumer', however when I hear that I think of threading.

什么是发电机,为什么要使用它?显然,无需引用任何书籍(除非您可以直接从书籍中找到体面,简单的答案).也许举一些例子,如果您感到慷慨!

What is a generator and why would you use it? Without quoting any books, obviously (unless you can find a decent, simplistic answer direct from a book). Perhaps with examples, if you're feeling generous!

推荐答案

注意:本文采用Python 3.x语法.

生成器只是一个返回对象的函数.可以调用next,这样每次调用都会返回一些值,直到引发StopIteration异常,这表明已生成所有值.这样的对象称为 iterator .

A generator is simply a function which returns an object on which you can call next, such that for every call it returns some value, until it raises a StopIteration exception, signaling that all values have been generated. Such an object is called an iterator.

普通函数使用return返回单个值,就像Java中一样.但是,在Python中,有一个替代方法,称为yield.在函数中的任何地方使用yield使其成为生成器.遵守以下代码:

Normal functions return a single value using return, just like in Java. In Python, however, there is an alternative, called yield. Using yield anywhere in a function makes it a generator. Observe this code:

>>> def myGen(n):
...     yield n
...     yield n + 1
... 
>>> g = myGen(6)
>>> next(g)
6
>>> next(g)
7
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

如您所见,myGen(n)是一个产生nn + 1的函数.每次调用 next 都会产生一个值,直到所有值都被屈服了. for在后台循环调用next,因此:

As you can see, myGen(n) is a function which yields n and n + 1. Every call to next yields a single value, until all values have been yielded. for loops call next in the background, thus:

>>> for n in myGen(6):
...     print(n)
... 
6
7

同样,有 生成器表达式 ,提供了一种简洁地描述某些常见类型的生成器的方法:

Likewise there are generator expressions, which provide a means to succinctly describe certain common types of generators:

>>> g = (n for n in range(3, 5))
>>> next(g)
3
>>> next(g)
4
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

请注意,生成器表达式非常类似于 列表推导 :

Note that generator expressions are much like list comprehensions:

>>> lc = [n for n in range(3, 5)]
>>> lc
[3, 4]

观察到生成器对象是一次生成的,但是它的代码不是 not 一次全部运行.只有对next的调用才实际执行(部分)代码.到达yield语句后,将停止在生成器中执行代码,并在该语句上返回值.然后,对下一个next的调用使执行在上一个yield之后剩下生成器的状态下继续执行.这是常规函数的根本区别:常规函数始终在顶部"开始执行,并在返回值时丢弃其状态.

Observe that a generator object is generated once, but its code is not run all at once. Only calls to next actually execute (part of) the code. Execution of the code in a generator stops once a yield statement has been reached, upon which it returns a value. The next call to next then causes execution to continue in the state in which the generator was left after the last yield. This is a fundamental difference with regular functions: those always start execution at the "top" and discard their state upon returning a value.

关于这个主题还有更多要说的话.例如可能send数据返回生成器(引用) .但这是我建议您在了解发电机的基本概念之前不要研究的东西.

There are more things to be said about this subject. It is e.g. possible to send data back into a generator (reference). But that is something I suggest you do not look into until you understand the basic concept of a generator.

现在您可能会问:为什么使用发电机?有两个很好的理由:

Now you may ask: why use generators? There are a couple of good reasons:

  • 使用生成器可以更简洁地描述某些概念.
  • 可以创建一个生成器来动态生成值,而不是创建一个返回值列表的函数.这意味着不需要构造列表,这意味着生成的代码具有更高的内存效率.这样一来,甚至可以描述太大而无法容纳在内存中的数据流.
  • 生成器提供了一种自然的方式来描述无限流.例如,考虑斐波那契编号:

  • Certain concepts can be described much more succinctly using generators.
  • Instead of creating a function which returns a list of values, one can write a generator which generates the values on the fly. This means that no list needs to be constructed, meaning that the resulting code is more memory efficient. In this way one can even describe data streams which would simply be too large to fit in memory.
  • Generators allow for a natural way to describe infinite streams. Consider for example the Fibonacci numbers:

>>> def fib():
...     a, b = 0, 1
...     while True:
...         yield a
...         a, b = b, a + b
... 
>>> import itertools
>>> list(itertools.islice(fib(), 10))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

此代码使用 itertools.islice 进行有限无限流中元素的数量.建议您仔细阅读 itertools 模块中的功能,因为它们是轻松编写高级生成器的基本工具.

This code uses itertools.islice to take a finite number of elements from an infinite stream. You are advised to have a good look at the functions in the itertools module, as they are essential tools for writing advanced generators with great ease.

   关于Python< = 2.6:在上述示例中,next是一个函数,该函数在给定的方法上调用方法__next__目的.在Python< = 2.6中,使用了一种稍有不同的技术,即o.next()而不是next(o). Python 2.7具有next()调用.next,因此您无需在2.7中使用以下内容:

   About Python <=2.6: in the above examples next is a function which calls the method __next__ on the given object. In Python <=2.6 one uses a slightly different technique, namely o.next() instead of next(o). Python 2.7 has next() call .next so you need not use the following in 2.7:

>>> g = (n for n in range(3, 5))
>>> g.next()
3

这篇关于了解Python中的生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆