假设:
numma = [1,2,3,4], n = 7
我希望以下代码返回:
[[1,2,3],[1,2,4]]
相反,它会返回一个包含以下四个副本的列表:
[1,2,4]
和六份副本:
[1,2,3,4]
该脚本旨在按顺序获取列表编号= numma的元素,并与它们形成一个新列表(this_chain),只要this_chain中元素的总和不超过n = 7。
当添加新元素会破坏该条件时,列表this_chain将附加到另一个列表(all_chains),然后该过程再次开始。如果原始列表(数字)用完元素,则当前this_chain将附加到all_chains并且脚本完成,返回名为all_chains的列表(列表)。
当我逐步运行它时,它遵循预期的行为,但是在到达return语句(步骤84)时,箭头向下移动半步,然后跳回到第一个语句,而不是返回all_chains并完成(for i in
...)。然后它返回并将当前this_chain的另一个副本附加到all_chains,依此类推,再执行66个步骤并返回上面提到的输出。
有人建议我迭代一个元组而不是列表,但是因为我想从迭代序列中删除元素,所以我看不出它是如何完成的。
我很困惑。我按照重要性顺序提出的四个问题如下:
为什么程序在到达退货声明后没有完成?我相信一个return语句总是会终止任何脚本。
鉴于上述行为,为什么脚本最终结束,而不是继续将有效列表的副本附加到名为all_chains的列表中?
为什么脚本会将无效元素附加到列表all_chains,即元素总和超过n = 7的列表?
为什么要删除(或修改)all_chains中的元素,以便它们不会出现在最终输出中,即使它们先前已附加到列表all_chains中了?
我的代码:
def chain(numbers, n, all_chains=[], sum=0, this_chain=[]):
for i in range(len(numbers)):
if numbers[i] not in this_chain:
sum += numbers[i]
if sum <= n:
this_chain.append(numbers[i])
chain(numbers, n, all_chains, sum, this_chain)
else:
if this_chain not in all_chains:
all_chains.append(this_chain)
mocha = numbers[:]
mocha.remove(this_chain[-1])
chain(mocha, n, all_chains, sum=0, this_chain=[])
all_chains.append(this_chain)
return all_chains
numma = [1,2,3,4]
chain(numma, 7, chains=[], sum=0, this_chain=[])
答案 0 :(得分:2)
- 为什么程序在达到退货声明后没有完成? 我相信一个return语句总会终止任何脚本。
醇>
返回不会终止脚本;它离开当前例程并将控制权返回给调用它的那个例程。当你进行递归调用时,它只是将控制返回到调用它的“elder”版本。
- 鉴于上述行为,为什么最终会有脚本 结束,而不是继续将有效列表的副本附加到列表中 叫all_chains?
醇>
它结束是因为所有活动的调用最终都会使它成为函数的底部,结束它们的执行。
- 为什么脚本会将无效元素追加到列表all_chains中, 也就是说,其元素总和超过n = 7的列表
醇>
问题是,当你返回尝试添加4时,你认为的列表是[1,2],但它实际上是[1,2,3],因为......好吧,请看下一点。
- 为什么要删除(或修改)all_chains中的元素,所以 它们不在最终输出中,即使它们是 以前附加到列表all_chains?
醇>
无论您将哪个附加到列表,都会附加对原始的引用,而不是本地副本。这来自于使用可变对象(如@tobias_k已经注意到的)。因此,当您将[1,2,3]附加到列表(多次)时,所有这些都是相同的对象。当您稍后错误地将4附加到列表中时(认为列表中只有[1,2]),您将 all 更改为[1,2,3,4]。我在下面的代码中解决了这个问题。
最后,由于缺少返回语句,您拥有所有这些额外的列表;而不是在你应该停止的时候,你会通过功能的其余部分,拨打更多电话,找到相同解决方案的更多副本。
我在代码中添加了一些内容,以便您可以查看执行情况。最重要的是,我添加了一些丑陋但有用的 print 语句来跟踪执行情况。我有以更易读的形式处理缩进,计数和参数打印的模块,您可以尝试查看最易读的内容。
我还将您的直接附加操作替换为副本,这样您就可以更好地区分问题并从错误中了解更多信息。
请记住,良好的选择来自经验。 经验来自糟糕的选择。
import copy
invocation = 0
def chain(numbers, n, all_chains=[], sum=0, this_chain=[]):
global invocation
invocation += 1
local_id = invocation
indent = " "
print indent*local_id, local_id, "ENTER", "\tsum", sum, "\tthis", this_chain, "\tall", all_chains
for i in range(len(numbers)):
if numbers[i] not in this_chain:
sum += numbers[i]
if sum <= n:
print indent*local_id, local_id, "append to this", sum, this_chain, numbers[i]
this_chain.append(numbers[i])
chain(numbers, n, all_chains, sum, this_chain)
else:
if this_chain not in all_chains:
print indent*local_id, local_id, "append to all 1", this_chain
all_chains.append(copy.copy(this_chain))
mocha = numbers[:]
mocha.remove(this_chain[-1])
chain(mocha, n, all_chains, sum=0, this_chain=[])
print indent*local_id, local_id, "append to all 2", this_chain
all_chains.append(copy.copy(this_chain))
print indent*local_id, local_id, "LEAVE", all_chains
return all_chains
numma = [1, 2, 3, 4]
result = chain(numma, 7)
print
for x in result:
print x
执行追踪:
1 ENTER sum 0 this [] all []
1 append to this 1 [] 1
2 ENTER sum 1 this [1] all []
2 append to this 3 [1] 2
3 ENTER sum 3 this [1, 2] all []
3 append to this 6 [1, 2] 3
4 ENTER sum 6 this [1, 2, 3] all []
4 append to all 1 [1, 2, 3]
5 ENTER sum 0 this [] all [[1, 2, 3]]
5 append to this 1 [] 1
6 ENTER sum 1 this [1] all [[1, 2, 3]]
6 append to this 3 [1] 2
7 ENTER sum 3 this [1, 2] all [[1, 2, 3]]
7 append to this 7 [1, 2] 4
8 ENTER sum 7 this [1, 2, 4] all [[1, 2, 3]]
8 append to all 2 [1, 2, 4]
8 LEAVE [[1, 2, 3], [1, 2, 4]]
7 append to all 2 [1, 2, 4]
7 LEAVE [[1, 2, 3], [1, 2, 4], [1, 2, 4]]
6 append to all 2 [1, 2, 4]
6 LEAVE [[1, 2, 3], [1, 2, 4], [1, 2, 4], [1, 2, 4]]
5 append to all 2 [1, 2, 4]
5 LEAVE [[1, 2, 3], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 4]]
4 append to all 2 [1, 2, 3]
4 LEAVE [[1, 2, 3], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 3]]
3 append to all 2 [1, 2, 3]
3 LEAVE [[1, 2, 3], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 3], [1, 2, 3]]
2 append to this 7 [1, 2, 3] 4
9 ENTER sum 7 this [1, 2, 3, 4] all [[1, 2, 3], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 3], [1, 2, 3]]
9 append to all 2 [1, 2, 3, 4]
9 LEAVE [[1, 2, 3], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 3], [1, 2, 3], [1, 2, 3, 4]]
2 append to all 2 [1, 2, 3, 4]
2 LEAVE [[1, 2, 3], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 3], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4]]
1 append to all 2 [1, 2, 3, 4]
1 LEAVE [[1, 2, 3], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 4], [1, 2, 3], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
[1, 2, 3]
[1, 2, 4]
[1, 2, 4]
[1, 2, 4]
[1, 2, 4]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]