调用python对象时超出了最大递归深度
我的目标是实例化一个名为arrow的类,这样我就可以拥有比1更多的arrow。我想从坐标200200开始,每100毫秒增加x 15。但当我尝试执行此代码时,它会给我以下错误:调用python对象时超出了最大递归深度,python,tkinter,Python,Tkinter,我的目标是实例化一个名为arrow的类,这样我就可以拥有比1更多的arrow。我想从坐标200200开始,每100毫秒增加x 15。但当我尝试执行此代码时,它会给我以下错误: File "game.py", line 25, in moveArrow self.after(100, self.moveArrow(arrow, xCoord+15, yCoord)) #repeat, changing x File "game.py", line 24, in moveArrow
File "game.py", line 25, in moveArrow
self.after(100, self.moveArrow(arrow, xCoord+15, yCoord)) #repeat, changing x
File "game.py", line 24, in moveArrow
arrow.place(x = xCoord, y = yCoord) #replace with new x,y
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1860, in place_configure
+ self._options(cnf, kw))
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1055, in _options
elif isinstance(v, (tuple, list)):
RuntimeError: maximum recursion depth exceeded while calling a Python object
移动箭头self.after(100,self.moveArrow(Arrow,xCoord+15,yCoord))#repeat,changing x“中的第25行“File”game.py也经常重复
from Tkinter import *
from random import randint
from PIL import ImageTk, Image
class App(Frame):
def __init__(self, master=None):
Frame.__init__(self, master, height=400, width=400)
self.master = master
self.master.bind('<Shift_L>', self.createArrow)
def createArrow(self, event):
self.arrow = Arrow(self)
self.arrow.moveArrow(self.arrow, 200, 200)
class Arrow(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.arrowImage = ImageTk.PhotoImage(Image.open("arrow.gif"))
Label(self, image=self.arrowImage).pack()
def moveArrow(self, arrow, xCoord, yCoord):
arrow.place_forget()
arrow.place(x = xCoord, y = yCoord)
self.after(100, self.moveArrow(arrow, xCoord+15, yCoord))
root = Tk()
root.title("Mein erstes Spiel")
app = App(master=root).pack()
root.mainloop()
从Tkinter导入*
从随机导入randint
从PIL导入ImageTk,图像
类应用程序(框架):
def uuu init uuu(self,master=None):
帧。u_初始__;(自,主,高度=400,宽度=400)
self.master=master
self.master.bind(“”,self.createArrow)
def createArrow(自身,事件):
self.arrow=箭头(self)
self.arrow.moveArrow(self.arrow,200200)
类箭头(框架):
定义初始(自我,主):
帧。\uuuu初始化(自,主)
self.arrowImage=ImageTk.PhotoImage(Image.open(“arrow.gif”))
标签(self,image=self.arrowImage).pack()
def移动箭头(self、arrow、xCoord、yCoord):
arrow.place_忘记()
箭头位置(x=xCoord,y=yCoord)
self.after(100,self.moveArrow(arrow,xCoord+15,yCoord))
root=Tk()
根标题(“Mein erstes Spiel”)
app=app(master=root).pack()
root.mainloop()
您正在调用self.moveArrow(arrow,xCoord+15,yCoord)
内部moveArrow()
方法
因此,在任何阶段都有一个无休止的递归,没有中断。
如果您想了解如何构建python递归方法,可以阅读
如果您想创建一些简单的移动效果,那么只需在一个循环上执行,假设您在x+200和y+200处移动箭头,生成一个简单的for循环,并延迟移动箭头
伪代码示例:
def moveArrow(....)
loop:
x += 10
y += 10
change_arrow_place(...)
产生问题的线是
self.after(100, self.moveArrow(arrow, xCoord+15, yCoord))x
因为moveArrow
没有中断条件。当我们在编程语言中使用递归时,递归需要break
条件,在这里它将不再调用相同的函数
例如:递归中的素数
int isPrime(int num,int i){
if(i==1){
return 1;
}else{
if(num%i==0)
return 0;
else
isPrime(num,i-1);
}
}
在上面的代码中断条件是if(i==1)
和if(num%i==0)
在这两个条件中,它将不调用isPrime
函数,递归将在那里终止
请添加中断条件,然后再次运行。关于此行的问题来源,其他答案是正确的:
self.after(100, self.moveArrow(arrow, xCoord+15, yCoord))
但答案是具体的:
请查看该方法的文档,了解如何正确实现该方法。像普通的函数调用一样调用它就可以做到这一点,并在控制流到达该函数调用时将程序放入无限循环中。在之后使用时,有两个选项:
传递时间参数,然后传递回调,然后传递回调参数:
self.after(100, self.moveArrow, arrow, xCoord+15, yCoord)
或者,使用lambda表达式保存函数调用:
self.after(100, lambda: self.moveArrow(arrow, xCoord+15, yCoord))
这绝对是在tkinter中制作动画的错误方法。你永远不应该在GUI中调用sleep
。@Bryan Oakley你是对的,因为睡眠会冻结整个GUI,这只是一个例子。@KobiK:如果你知道这是错误的方法,你不应该给出一个例子。在我写这篇评论时,这是公认的答案。因此,提出问题的人认为这是正确的方法,并将学会一种不正确的编写代码的方法。@Bryan Oakley问题是不间断的递归,与睡眠无关,我将删除睡眠部分,因为你的评论是正确的。@KobiK:问题是递归,但不是因为没有休息。问题是首先存在递归。正确调用
之后的时,不存在递归。这个答案有正确的解释:你对这行的解释是正确的,你对解释的解释是错误的。如果你能解释我在解释中什么是错误的,那么我的观点也会很清楚:)正确的解释在这个答案中:。问题与需要“中断”条件无关。问题在于如何在调用
后调用。感谢@BryanOakley的回复。这里有很多好信息:。。。除此之外,只要做点东西,你就会明白的