我正在阅读Python烹饪书,目前正在研究生成器。我觉得很难理解。

由于我有Java背景,那么Java中是否有对等的语言?这本书讲的是“生产者/消费者”,但当我听到这个词时,我想到了线程。

什么是发电机,你为什么要用它?显然,没有引用任何书籍(除非你能直接从一本书中找到一个体面、简单的答案)。如果你慷慨的话,还可以举个例子!


当前回答

Java中没有对等的。

这里有一个有点做作的例子:

#! /usr/bin/python
def  mygen(n):
    x = 0
    while x < n:
        x = x + 1
        if x % 3 == 0:
            yield x

for a in mygen(100):
    print a

生成器中有一个从0到n运行的循环,如果循环变量是3的倍数,则生成该变量。

在for循环的每次迭代中,都会执行生成器。如果这是生成器第一次执行,它将从开始开始,否则它将从上一次生成的时间开始。

其他回答

Java中没有对等的。

这里有一个有点做作的例子:

#! /usr/bin/python
def  mygen(n):
    x = 0
    while x < n:
        x = x + 1
        if x % 3 == 0:
            yield x

for a in mygen(100):
    print a

生成器中有一个从0到n运行的循环,如果循环变量是3的倍数,则生成该变量。

在for循环的每次迭代中,都会执行生成器。如果这是生成器第一次执行,它将从开始开始,否则它将从上一次生成的时间开始。

它有助于明确区分函数foo和生成器foo(n):

def foo(n):
    yield n
    yield n+1

Foo是一个函数。 Foo(6)是一个生成器对象。

使用生成器对象的典型方式是在循环中:

for n in foo(6):
    print(n)

循环打印

# 6
# 7

可以将生成器视为可恢复函数。

Yield的行为类似于return,产生的值被生成器“返回”。然而,与return不同的是,下一次生成器被请求一个值时,生成器的函数foo将从它停止的地方恢复——在最后一个yield语句之后——并继续运行,直到遇到另一个yield语句。

在幕后,当您调用bar=foo(6)时,生成器对象bar为您定义了一个下一个属性。

你可以自己调用它来获取foo产生的值:

next(bar)    # Works in Python 2.6 or Python 3.x
bar.next()   # Works in Python 2.5+, but is deprecated. Use next() if possible.

当foo结束时(并且没有更多的输出值),调用next(bar)将抛出StopInteration错误。

使用列表推导式的经验表明,它们在Python中具有广泛的实用性。然而,许多用例不需要在内存中创建一个完整的列表。相反,它们每次只需要迭代一个元素。

例如,下面的求和代码将在内存中构建一个完整的方块列表,遍历这些值,当引用不再需要时,删除列表:

Sum ([x*x for x in range(10)])

通过使用生成器表达式来节省内存:

求和(x*x for x in range(10))

容器对象的构造函数也有类似的好处:

s = Set(word  for line in page  for word in line.split())
d = dict( (k, func(k)) for k in keylist)

生成器表达式对于sum(), min()和max()这样的函数特别有用,它们将可迭代输入减少为单个值:

max(len(line)  for line in file  if line.strip())

more

我相信迭代器和生成器的第一次出现是在Icon编程语言中,大约20年前。

你可能会喜欢Icon的概述,它可以让你在不关注语法的情况下理解它们(因为Icon是一种你可能不知道的语言,Griswold是在向来自其他语言的人解释他的语言的好处)。

在阅读了几段之后,生成器和迭代器的效用可能会变得更加明显。

我给出了这段代码,解释了关于生成器的3个关键概念:

def numbers():
    for i in range(10):
            yield i

gen = numbers() #this line only returns a generator object, it does not run the code defined inside numbers

for i in gen: #we iterate over the generator and the values are printed
    print(i)

#the generator is now empty

for i in gen: #so this for block does not print anything
    print(i)