[英]Python recursion depth exceeded limit exceeded, and don't know how to delete recursion
Maybe the problem can be solved by deleting all those functions, can't it? 也许可以通过删除所有这些功能来解决问题,不是吗? However, i really don't know what to do to get the source work.
但是,我真的不知道该怎么做才能完成源工作。 By the way, it just simulates a horse in a chesstable, going around and around, randomly, trying to visit each square once;
顺便说一句,它只是在国际象棋桌上模拟一匹马,随机地四处走动,试图访问每个广场一次。 and I get a recursion depth exceeded error.
我得到一个递归深度超过错误。
import random
def main():
global tries,moves
tries,moves=0,0
restart()
def restart():
global a,indexes,x,y
a=[[0 for y in range(8)] for x in range(8)] #Costrutto chic
indexes=[x for x in range(8)]
#Random part
x=random.randint(0,7)
y=random.randint(0,7)
a[x][y]=1
start()
def start():
global i,indexes,moves,tries
i=0
random.shuffle(indexes) #List filled with random numbers that i'll use as indexes
while i<=7:
if indexes[i]==0:
move(-2,-1)
elif indexes[i]==1:
move(-2,1)
elif indexes[i]==2:
move(-1,-2)
elif indexes[i]==3:
move(-1,2)
elif indexes[i]==4:
move(1,-2)
elif indexes[i]==5:
move(1,2)
elif indexes[i]==6:
move(2,-1)
elif indexes[i]==7:
move(2,1)
i+=1
for _ in a:
if 0 in _:
print "Wasted moves: %d"%(moves)
tries+=1
moves=0
restart()
print "Success obtained in %d tries"%(tries)
def move(column,row):
global x,y,a,moves
try: b=a[x+row][y+column]
except IndexError: return 0
if b==0 and 0<=x+row<=7 and 0<=y+column<=7:
x=x+row
y=y+column
a[x][y]=1
moves+=1
start()
else: return 0
try :main()
#except: print "I couldn't handle it" <-Row added to prevent python from returning a huge amount of errors
EDIT: This is the modified version, which still does not works, but at least it's an improvement: 编辑:这是修改后的版本,它仍然无法正常工作,但至少是一个改进:
import random
def move((column,row),x,y):
try: cell=squares_visited[x+row][y+column]
except IndexError: return x,y ## NONE TYPE OBJECT
if cell==0 and 0<=x+row<=7 and 0<=y+column<=7:
x+=row
y+=column
squares_visited[x][y]=1
return x,y ## NONE TYPE OBJECT
squares_visited=[[0] * 8 for _ in range(8)]
x=random.randint(0,7)
y=random.randint(0,7)
squares_visited[x][y]=1
moves=[(-2,-1),(-2,1),(-1,-2),(-1,2),(1,-2),(1,2),(2,-1),(2,1)]
indexes=list(range(8))
tries=0
print "The horse starts in position %d,%d"%(x,y)
while True:
random.shuffle(indexes)
for _ in indexes:
cells=move(moves[indexes[_]],x,y) ##Passing as arguments x and y looks weird
x=cells[0]
y=cells[1]
#If you out this for cicle, there are no legal moves anymore(due to full completion with 1, or to lack of legit moves)
for _ in squares_visited:
if 0 in _:
squares_visited=[[0] * 8 for _ in range(8)]
tries+=1
else:
print "You managed to do it in %d tries."%(tries)
This code has a lot of problems -- enough that it's worth going over in full: 这段代码有很多问题-足以值得一遍:
import random
def main():
global tries,moves
The first of many examples of over-use of global variables. 过度使用全局变量的许多例子中的第一个。 When possible, pass parameters;
如果可能,传递参数; or create a class.
或创建一个类。 This is a general strategy that will help you construct more comprehensible (and thus more debuggable) algorithms;
这是一种通用策略,可帮助您构建更易于理解(从而更易于调试)的算法; and in a general sense, this is part of why your code fails -- not because of any particular bug, but because the complexity of your code makes it hard to find bugs.
从一般意义上讲,这就是代码失败的部分原因-不是因为任何特定的错误,而是因为代码的复杂性使得很难发现错误。
tries,moves=0,0
restart()
def restart():
global a,indexes,x,y
Why do you name your board a
? 为什么你命名你的主板
a
? That's a terrible name! 那是一个糟糕的名字! Use something descriptive like
squares_visited
. 使用诸如
squares_visited
描述性squares_visited
。
a=[[0 for y in range(8)] for x in range(8)] #Costrutto chic
indexes=[x for x in range(8)]
Minor: in python 2, [x for x in range(8)] == range(8)
-- they do exactly the same thing, so the list comprehension is unnecessary. 次要:在python 2中,
[x for x in range(8)] == range(8)
-它们做的完全相同,因此不需要列表理解。 In 3, it works a little differently, but if you want a list (rather than a range
object) just pass it to list
as in ( list(range(8))
). 在3中,它的工作原理略有不同,但是如果您想要一个列表 (而不是
range
对象),只需像( list(range(8))
) list
那样将其传递给list
。
#Random part
x=random.randint(0,7)
y=random.randint(0,7)
a[x][y]=1
start()
So my understanding of the code so far is that a
is the board, x
and y
are the starting coordinates, and you've marked the first spot visited with a 1
. 因此,到目前为止,我对代码的理解是,
a
是木板, x
和y
是起始坐标,并且您已经用1
标记了访问的第一个地点。 So far so good. 到现在为止还挺好。 But then things start to get hairy, because you call
start
at the end of restart
instead of calling it from a top-level control function. 但是事情开始变得繁琐,因为您在
restart
结束时调用了start
,而不是从顶级控制函数中调用它。 That's theoretically OK, but it makes the recursion more complicated than necessary; 从理论上讲这是可以的,但是这会使递归变得不必要的复杂。 this is another part of your problem.
这是您问题的另一部分。
def start():
global i,indexes,moves,tries
Argh more globals... 更多全球人物...
i=0
random.shuffle(indexes) #List filled with random numbers that i'll use as indexes
while i<=7:
if indexes[i]==0:
move(-2,-1)
elif indexes[i]==1:
move(-2,1)
elif indexes[i]==2:
move(-1,-2)
elif indexes[i]==3:
move(-1,2)
elif indexes[i]==4:
move(1,-2)
elif indexes[i]==5:
move(1,2)
elif indexes[i]==6:
move(2,-1)
elif indexes[i]==7:
move(2,1)
i+=1
Ok, so what you're trying to do is go through each index in indexes
in sequence. 好了,你正在试图做的是要经过在各指标
indexes
序列。 Why are you using while
though? 你为什么要用
while
? And why is i
global?? 为什么
i
是全球性的? I don't see it being used anywhere else. 我看不到在其他任何地方使用它。 This is way overcomplicated.
这太复杂了。 Just use a
for
loop to iterate over indexes
directly, as in 只需使用
for
循环即可直接遍历indexes
,如
for index in indexes:
if index==0:
...
Ok, now for the specific problems... 好了,现在针对具体问题...
for _ in a:
if 0 in _:
print "Wasted moves: %d"%(moves)
tries+=1
moves=0
restart()
print "Success obtained in %d tries"%(tries)
I don't understand what you're trying to do here. 我不明白您要在这里做什么。 It seems like you're calling
restart
every time you find a 0
(ie an unvisited spot) on your board. 似乎您每次在板上找到
0
(即未访问的位置)时都在调用restart
。 But restart
resets all board values to 0
, so unless there's some other way to fill the board with 1
s before hitting this point, this will result in an infinite recursion. 但是
restart
会将所有电路板的值重置为0
,因此,除非有其他方法在达到这一点之前用1
s填充电路板,否则将导致无限递归。 In fact, the mutual recursion between move
and start
might be able to achieve that in principle, but as it is, it's way too complex! 事实上,之间的相互递归
move
和start
也许能够实现这一原则,但因为它是,它的方式太复杂了! The problem is that there's no clear recursion termination condition. 问题在于没有明确的递归终止条件。
def move(column,row):
global x,y,a,moves
try: b=a[x+row][y+column]
except IndexError: return 0
if b==0 and 0<=x+row<=7 and 0<=y+column<=7:
x=x+row
y=y+column
a[x][y]=1
moves+=1
start()
else: return 0
Here, in principle, the idea seems to be that if your move hits a 1
or goes off the board, then the current branch of the recursion terminates. 原则上,这里的想法似乎是,如果您的举动达到
1
或偏离板,则递归的当前分支终止。 But because i
and indexes
are global above in start
, when start
is re-called, it re-shuffles indexes
and resets i
to 0! 但是因为
i
和indexes
以上是在全球start
,当start
重新调用,它重新洗牌indexes
和重置i
比0! The result is sheer chaos! 结果是混乱! I can't even begin to comprehend how that will effect the recursion;
我什至无法理解这将如何影响递归。 it seems likely that because
i
gets reset at the beginning of start
every time, and because every successful call of move
results in a call of start
, the while
loop in start will never terminate! 好像是因为每次
i
都在start
的开始处被重置,并且每次成功调用move
导致调用start
,所以start
中的while
循环永远不会终止!
I suppose it's possible that eventually this process will manage to visit every square, at which point things might work as expected, but as it is, this is too complex even to predict. 我想这个过程最终可能会成功访问每个广场,这时事情可能会按预期进行,但实际上,这甚至太复杂了,甚至无法预测。
try :main()
#except: print "I couldn't handle it" <-Row added to prevent python from returning a huge amount of errors
Not sure what you mean by that last line, but it doesn't sound like a good sign -- you're papering over an error instead of finding the root cause. 不确定最后一行的含义,但这听起来似乎不是一个好兆头-您是在为错误而不是根本原因寻找答案。
I'm going to play with this code a bit and see if I can get it to behave marginally better by de-globalizing some of its state... will report back soon. 我将使用此代码一点,看看是否可以通过取消全局化某些状态来使其表现得更好一些……将尽快报告。
Update : 更新 :
Ok I de-globalized indexes
as described above. 好吧,如上所述,我取消了
indexes
的全球化。 I then replaced the start
/ restart
recursion with an infinite loop in restart
, a return
statement in start
where the call to restart
used to be, and a sys.exit()
at the end of start
(to break out of the infinite loop on success). 然后我更换了
start
/ restart
递归在一个无限循环restart
,一return
在声明start
,其中的号召restart
曾经是,和sys.exit()
在年底start
(打出来的无限循环的上成功)。 The result behaves more as expected. 结果表现得比预期的要好。 This is still poor design but it works now, in the sense that it recursively tries a bunch of random paths until every local position has been visited.
这仍然是较差的设计,但从某种意义上说,它递归地尝试了一堆随机路径,直到访问了每个本地位置为止,它现在可以工作。
Of course it still doesn't ever succeed; 当然,它仍然永远不会成功。 it just keeps looping.
它只是不断循环。 Actually finding a solution will probably require a lot more rethinking of this algorithm!
实际上,找到解决方案可能需要对这种算法进行更多的重新思考! But following my above suggestions should help some, at least.
但是遵循我的上述建议至少应该有所帮助。
start()
and move()
call each other, making it an indirect recursive call BUT the move()
return
startment get out of move()
and notout of the recursion. start()
和move()
互相调用,这使其成为间接递归调用,但move()
return
起点从move()
退出而不是从递归退出。
You see, when you are calling a function, that calls a function that calls a functions, it all goes in a stack that reference each calls. 您会看到,在调用一个函数时,即调用一个调用函数的函数时,所有这些都放在引用每个调用的堆栈中。 When you get a your final result, you are supposed to go backward, and unstack these function calls.
当您获得最终结果时,应该向后退,并拆开这些函数调用的堆栈。
Here, you don't, you call move()
, that calls start()
, and it it returns something then you just keep going deeper in the stack. 在这里,您没有,您调用了
move()
,即调用了start()
,它返回了一些内容,然后您就可以继续深入栈中了。
Try to make an iterative version of your code. 尝试制作代码的迭代版本。 Recursion is hard, start with something easier.
递归很困难,从更轻松的事情开始。
If you do want to persist in the recursive version, make move()
call itself, and then go backward in the stack from it self once it reach the out condition. 如果您确实想保留递归版本,请先调用
move()
本身,然后在达到out条件后从其自身返回堆栈。 It will be clearer than dealing with recursive calls from two functions. 这比处理来自两个函数的递归调用要清晰得多。
BTW: 顺便说一句:
while
loop is not necessary. while
循环不是必需的。 Replace it with a for loop on indexes if/elif
statement is not necessary, replace it with a dictionary if/elif
语句,将其替换为字典 You should end up with somthing like this: 您应该最终得到这样的东西:
for i in indexes:
move(*MOVES[i])
MOVES
, being a dict of values of i
associated with params for move()
. MOVES
,是与move()
参数相关联的i
值的指示。
[x for x in range(8)]
can be written range(8)
[[0 for y in range(8)] for x in range(8)]
can be written [[0] * 8 for x in range(8)]
[x for x in range(8)]
写入range(8)
[[0 for y in range(8)] for x in range(8)]
可以写入[[0] * 8 for x in range(8)]
range()
can be replaced by xrange()
range()
可以替换为xrange()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.