Python Tkinter-RecursionError:调用Python对象时超出了最大递归深度

Python Tkinter-RecursionError:调用Python对象时超出了最大递归深度,python,tkinter,Python,Tkinter,这是一个我自己无法解决的奇怪问题。基本上,我正在使用python 3.6和Tkinter制作“扫雷舰”。游戏进行得很好,直到一场艰苦的游戏进行到一半(如果其他游戏拖得更长,就会发生这种情况),你点击一个棋子,然后控制台出现错误。过了一会儿,在能够玩更多的动作之后,游戏崩溃了。请原谅“临时”代码,这不是我最好的作品,因为它从来没有被任何人看到过 (我没有包括程序中的所有代码) 从tkinter导入* 随机输入 root=Tk() 按钮=[] images={“X”:PhotoImage(file

这是一个我自己无法解决的奇怪问题。基本上,我正在使用python 3.6和Tkinter制作“扫雷舰”。游戏进行得很好,直到一场艰苦的游戏进行到一半(如果其他游戏拖得更长,就会发生这种情况),你点击一个棋子,然后控制台出现错误。过了一会儿,在能够玩更多的动作之后,游戏崩溃了。请原谅“临时”代码,这不是我最好的作品,因为它从来没有被任何人看到过

(我没有包括程序中的所有代码)

从tkinter导入*
随机输入
root=Tk()
按钮=[]
images={“X”:PhotoImage(file=“Mine.gif”),“X/”:PhotoImage(file=“MineSlash.gif”),“F”:PhotoImage(file=“Flag.gif”)}
颜色={1:“0008f9”,2:“10cc00”,3:“ff4f1e”,4:“4b00a8”,5:“bc0000”,6:“00cbdd”}
董事会=[]
地雷=[]
按钮=[]
minesLeft=10
numMines=10
boardSize=8
死=假
minesLeftLabel=标签(font=“Verdana 10粗体”)
开始按钮=[]
def ButtonCreate():
按钮(root,text=“Restart”,width=8,height=1,font=“Verdana 10 bold”,command=Restart)。网格(行=0,列=0,列span=3)
全球地雷标签
minesLeftLabel.grid(行=0,列=4,列span=2)
minesLeftLabel.config(text=str(minesLeft))
对于范围内的y(板尺寸):
圣殿骑士=[]
对于范围内的x(板尺寸):
按钮=按钮(根,文本=板[y][x],bg=“#eaeaea”,宽度=2,高度=1,font=“Verdana 10 bold”)
button.bind(“”,lambda事件,x=x,y=y:MinePressed(x,y,False))
button.bind(“”,lambda事件,x=x,y=y:MinePressed(x,y,True))
按钮网格(行=y+2,列=x)
tempList.append(按钮)
按钮。追加(模板列表)
def检查(x,y):
按钮[y][x]。配置(text=”“,fg=“灰色”,bg=“#e5”,浮雕=凹陷)
对于范围(-1,2)内的YPO:
对于范围(-1,2)内的XPO:

如果y+yPos>=0且y+yPos=0且x+xPos,则问题或至少一个问题在于您多次调用
mainloop
,并且您是从事件处理程序调用它的。这就是最终导致无限递归的原因

顾名思义,
mainloop
本身就是一个无限循环。它一直运行,直到主窗口被破坏。当您按下某个键或按钮时,
mainloop
将运行与该键或按钮关联的命令。如果该命令被按下,它将最终导致从原始调用
mainloop
的内部再次调用
mainloop

因为
mainloop
永远不会退出(因为根窗口永远不会被破坏),所以有一个无限循环调用一个无限循环调用一个无限循环,…,而这些内部循环都不会退出。当运行
mainloop
的1000个副本时,最终会耗尽堆栈空间

您需要将
root.mainloop()
移出
MinePressed
并将其作为文件的最后一行,例如:

SelectSize()
input()
root.mainloop()

尽管如此,它可能位于
input()
——我不知道这行代码的用途。

如果遇到最大递归错误,几乎可以肯定是因为递归
checkneights
函数。如果您有8x8板,板上的最大点数为64。默认的递归限制是1000,这意味着您要“检查一个邻居”1000次,而检查的邻居不可能超过64个。我知道您要去哪里了。我已经解决了这个问题(因为我已经发布了一个解决方案),但在我的例子中,有超过64个邻居需要检查。该程序目前尚未优化,因此,一个工件会检查其周围的所有8个邻居,如果其中一个没有值(为空白点),则它会对该磁贴执行相同的操作,它将检查所有8个邻居(除了调用该磁贴上函数的邻居)。(续)但是,尽管如此,在一次调用中,它实际上不会超过1000次递归,它会随着时间的推移而累积,即使前一组邻居检查的递归已经完成。Python中递归的奇怪集成,但正如在解决方案中所说的,最好的解决方法是将其放入一个循环中(由于我创建递归函数的方式,这需要一些额外的工作)。感谢帮助Python的实现与任何其他编程语言都没有什么不同。这种行为是由您的代码造成的,而不是python的递归实现。这就是堆栈从未被删除或清除的原因。你说得对:)非常感谢!这解释了为什么堆栈空间没有被清除,从而将递归循环堆叠在彼此的顶部,直到达到最大递归限制。input()存在的原因实际上是为了使程序不会关闭,但现在我了解了mainloop()的功能,它可以完全替换input()语句!谢谢你的帮助!我现在有一些难以解释的问题。当我点击一个按钮时,它应该进入relief=SUNKEN模式,我已经检查过了,它甚至会执行该行,以及该行中的每一个其他命令(在“MinePressed”中“root.update_idletasks()”上方的行)。但是,除非我将root.mainloop()保持在那里,否则它不会保持下沉状态。最奇怪的是,通过checkneights()函数更新并成功调用relief=sinken的每个按钮都保持凹陷状态。感谢您的帮助,并修复了以前的问题。只需将“root.mainloop()”放在文件末尾,删除所有其他的“root.mainloop()”和“root.update_idletasks()”,并将此行:button.bind(“”,lambda event,x=x,y=y:MinePressed(x,y,False))更改为:button.config(command=lamda x=x,y=y:MinePressed(x,y,False)),谢谢