要理解这是怎么回事,它有助于打印发电机的输出的n
多个依次增加的值:
>>> for i in range(5):
print(list(gen(i)))
[()]
[(1,)]
[(1, 1), (2,)]
[(1, 1, 1), (1, 2), (3,)]
[(1, 1, 1, 1), (1, 1, 2), (2, 2), (1, 3), (4,)]
每个序列的计算是基于之前的一个。下面是它如何工作的行一行解释:
if n == 0:
yield()
return
发电机的这些前几行是基本情况,其中n
为零。 return
语句使得它在产生空元组之后退出,而不是继续执行其余的代码。
for p in gen(n-1):
这是该函数的递归步骤。由于gen
是一个生成器,因此它是用一个循环完成的,所以其余代码将重复运行,p
从递归结果中获取不同的值。
yield (1,) + p
这是一条重要的线。这样做是通过将一个1
连接到值p
的前面形成的新元组产生出发生器。如果p
是空元组,这将是一个1元组。如果p
已经有一些值,则元组将变长。
if p and (len(p)<2 or p[1] > p[0]):
这是一个复杂的条件。第二个检查len(p)<2
确实可以写成len(p)==1
,因为p and
部分在开始时已经排除了p
为空。
p
可以有两种值,以通过。 p
只有一个值,或者它有更多的值,其第一个值小于第二个值。所以(3,)
会通过,如(1,2)
,但(1,1,1)
不会。
yield (p[0] + 1,) + p[1:]
这是另一个元组连接。它将p
的第一个值增加1,然后将其与p
的其余部分(使用切片)连接起来。所以(3,)
将成为(4,)
(具有层为空),(1,2)
变得(2,2)
等
所以,现在让我们通过我们上面看到运行结果。
[()]
随着n
等于0时,基本情况被击中,你会得到一个空的元组产生。
[(1,)]
随着n
等于1,则循环运行一次,并连接(1,)
到空的元组,产生1元组(1,)
。 if
条件的第一部分未通过,因为p
为空。
[(1,1), (2,)]
随着n
等于2,循环仍然只运行一次。首先通过连接(1,)
与其自身得到(1,1)
得到(1,1)
。但是这一次,if
块被运行,因为p
只有一个值。所以它也产生(p[0]+1,) + p[1:]
。该片的部分是空元组,但第一部分是(2,)
。
[(1,1,1), (1,2), (3,)]
现在终于循环得到运行不止一次!但是,它第一次将(1,)
连接到(1,1)
的前面,并且由于if
声明的条件未得到满足,这就是它的全部。然而,在第二次通过时,它产生两个值,一旦连接(1,)
和(2,)
,然后将(2,)
递增到(3,)
。
[(1, 1, 1, 1), (1, 1, 2), (2, 2), (1, 3), (4,)]
这一个我会留给你,走过去。就像上面的情况一样,p
将采用来自上一级调用((1,1,1), (1,2), (3,)
)的每个值,对于每个值,它将产生一个或两个新结果。
你对此感到困惑吗? – Blender 2013-02-21 20:42:50
我真的很喜欢,如果你可以请请解释每一行Please.That将帮助我更好地了解如何收益作品。谢谢 – 2013-02-21 20:46:48
可能重复[的Python yield关键字解释](http://stackoverflow.com/questions/231767/the-python-yield-keyword-explained) – 2013-02-21 20:50:46