2014-10-29 155 views
-1

发电机物P我使用Python 3.4 *和我想要执行下面的代码:蟒蛇错误:在0x02DAC198

def P(n): 
    if n == 0: 
     yield [] 
     return 

    for p in P(n-1):   
     p.append(1) 
     yield p 
     p.pop() 
     if p and (len(p) < 2 or p[-2] > p[-1]): 
      p[-1] += 1 
      yield p 


print(P(5)) # this line doesn't make sense 


for i in P(5): # but this line does make sense thanks to furkle 
    print(i) 

但我正在逐渐<generator object P at 0x02DAC198>而不是输出。

有人可以解释我的代码中需要修复的地方吗?我不认为py喜欢函数名P,但我可能是错的。

编辑:furkle澄清<generator object P at 0x02DAC198>

顺便说一下,我目前正在尝试编写自己的修改过的分区函数,并试图理解与经典设置相对应的这一个。

+2

您的代码*按设计工作*。这里没有错误,因为你使用了yield,所以你产生了一个generator函数。你预期会发生什么? – 2014-10-29 16:50:04

+1

使用'list(P(5))'会给你空列表,但是我的猜测是这并不是你想要看到的,要么... – dano 2014-10-29 16:52:13

+1

我认为这是我第一次修改后的生成器看到。它产生的列表不是空的,然后清空它们,如果你继续阅读。 – 2014-10-29 17:22:10

回答

0

我认为你误解了发电机的概念。生成器对象就像一个列表,但是您可以懒惰地遍历其结果,而无需等待整个列表的构建。对返回生成器的函数调用操作将不会对生成器生成的每个项目依次执行该操作。

如果你想打印P的所有输出(5),你应该写:

for i in P(5): 
    print(i) 

如果你只是想打印由发电机,在很大程度上似乎击败返回的内容的列表发电机的目的。

0

这段代码很多事情都是错误的,你对发生器的工作原理和用途有所了解。

首先,关于您的print声明,这正是它应该打印的内容。发电机是永远不会隐式扩大,因为不能保证发电机永远不会终止。这是完全有效的,有时甚至是非常理想的,来构造一个产生无穷序列的发生器。为了得到你想要的东西(我以为是产生类似的列表输出),你会怎么做:

print(list(P(5)) 

但是,这引出了我的第二点;生成器的顺序生成值(对于它们的使用率为99%,除非您将它用作协同程序)。你正在尝试使用你的生成器来构造一个列表;然而,如果n不是0这永远不会产量一个值,并会立即返回。如果你的目标是建立一个发电机,使的1“给定长度的List,它应该是这样的:

def P(n): 
    while n >= 0: 
     yield n 
     n -=1 

这将产生1米的长度n的序列。要获取列表表单,您需要执行list(P(n))

我建议你再读一遍Generator Documentation,对他们有更好的感受,看看他们是否真的是这份工作的正确工具。

+0

@MeeSeong没问题。请注意,为了生成1的序列,'[1 for _i in range(n + 1)]'会更有效率。我只是提供了生成器示例,因为这就是你所问的。 – aruisdante 2014-10-29 17:30:13

0

在阅读函数时,我试着找出调用会产生什么。让我们先从完整的原始代码:

def P(n): 
    if n == 0: 
     yield [] 
     return 

    for p in P(n-1):   
     p.append(1) 
     yield p 
     p.pop() 
     if p and (len(p) < 2 or p[-2] > p[-1]): 
      p[-1] += 1 
      yield p 


print(P(5)) # this line doesn't make sense 

好了,所以它调用P(5)。因为这不是0,P递归,直到我们到达P(0)这产生一个空列表。这是第一次接收价值p。然后P(1)1附加到该列表中,并将其产生到P(2),其重复该过程..等等。所有相同的名单,最初由P(0)创建,并最终以[1,1,1,1,1]P(5)排除 - 但随后发生了奇迹。我们称之为第一个列表l0

当您向发电机询问第二项时,控制返回到P(5),该值现在从l0中删除一个值。根据一系列条件,它可能会增加最后一个值,并再次产生p,即l0。所以我们收到的第一件物品一直在变化,而我们要求第二件物品。这将最终结束,而是意味着有这两者之间的区别:

print list(P(5)) # Eventually prints a list of l0 which has been emptied! 
for item in P(5): 
    print item # Prints l0 at each point it was yielded 

In [225]: for i in P(5): print i 
[1, 1, 1, 1, 1] 
[2, 1, 1, 1] 
[2, 2, 1] 
[3, 1, 1] 
[3, 2] 
[4, 1] 
[5] 

In [226]: list(P(5)) 
Out[226]: [[], [], [], [], [], [], []] 

这就是为什么我把它叫做 - 修改后;它返回的值在它们被生成之后保持改变(因为它们实际上是被操纵的同一个对象)。