"else" 在 "if" 之前执行的语句 在 Python 中使用 `undo` 之后的语句

"else" statement executed before "if" statement after `undo` is used in Python

我创建了以下功能,允许用户将 Python 海龟的形状更改为图像 he/she 从文件对话框中选择当特定按钮被弹出时文件对话框按下:

def TurtleShape(iop = None):
   # "iop" is supposed to be an image path
   try:
       manipulateimage.config(state = NORMAL)
       flipButton.config(state = NORMAL)
       mirrorButton.config(state = NORMAL)
       originalButton.config(state = NORMAL)
       resetturtle.config(state = NORMAL)
       rotateButton.config(state = NORMAL)
       global klob
       # The following "if-else" statement uses the "iop" argument's value as the value for "klob" if `iop` is NOT `None`
       if iop != None:
           klob = iop
           print("lmcv")
       else:
           klob = filedialog.askopenfilename()
           print("klobby")
       global im
       im = Image.open(klob)
       pictures.append(im)
       edited.clear()
       print(im)
       im.save(klob + '.gif', "GIF")
       register_shape(klob + '.gif')
       shape(klob + '.gif')
       update()
   except:
       pass

上面的函数也应该使用 iop 参数的值作为海龟的图像,如果它不是 None

现在,考虑一下这种情况;你画了一堆东西,将海龟设置为图像,就在你要标记图像时,你不小心按下了将海龟重置为正常形状的按钮(是的,那个按钮存在于我的程序)。 哦不!如果不经过所有步骤再次打开和编辑它,您将如何取回它?好吧,这就是我的 undoHandler 函数(如下所示)发挥作用的地方。它实际上只是撤消使用许多堆栈调用的最后一个函数,我将其创建为 deques。如果你精通 Python:

就很简单了
def undoHandler():
   if len(function) > 0 and draw.drawing == True:
      undoHandler.handling = True
      if not hasattr(undoHandler, "counter"):
         undoHandler.counter = 0
      undoHandler.counter += 1
      # clear the canvas
      Clear()
      # Pop a point object from function deque
      function.pop()
      penup()
      goto(-200, 100)
      pendown()

      try:
          # Execute everything up to point before last function called
          for i in function:
             # Set canvas and turtle to previous state
             tsd = i.recieveshape()
             shape(tsd)
             mndf = i.recieveheading()
             setheading(mndf)
             hk = i.getletterheight()
             global letter_height 
             letter_height = hk
             rk = i.getletterwidth()
             global letter_width
             letter_width = rk
             milk = i.getspacewidth()
             global space_width
             space_width = milk
             hw = i.getwidth()
             width(hw)
             op = i.getcolor()
             try:
                color(op)
             except:
                for g in colors:
                   cp = g.getcolor2()
                   colormode(255)
                   color(cp)
             # Get function wrapped in Point object and execute it
             j = i.getfunction()
             j()
             # Following is the code block where the issue occurs. Basically, if the function being run is equal to `TurtleShape`, then do the following...
             if j.__name__ == "TurtleShape":
                 # `hfl` is a deque that holds all of the `pictures` deque's contents as it is cleared when the turtle is set to its default state
                 pictures.extend(hfl)
                 lmcv = pictures.pop()
                 pictures.append(lmcv)
                 try:
                     # Resize image to previous size if user changes it. Otherwise, skip this.
                     bun = picwidth.pop()
                     picwidth.append(bun)
                     mun = picheight.pop()
                     picheight.append(mun)
                     clob = lmcv.resize((int(bun), int(mun)), Image.ANTIALIAS)
                 except:
                     clob = lmcv
                 clob.save(klob + str(undoHandler.counter) + ".gif")
                 # Use the `clob.save` output from above as source image in `TurtleShape` function (this is where issue occurs)
                 TurtleShape(klob + str(undoHandler.counter) + ".gif")
                 print("Undone!")
             else:
                 pass
      except:
         pass

基本上这里发生的是它从队列中获取函数(包装在 Point 对象中),主要函数在调用时通过该队列。然后函数被附加到 function 双端队列,之后,当用户调用 undoHandler 时,屏幕被清除,最新的值从 function 双端队列中弹出,以便所有其他动作 除了 最后一个将再次执行。我面临的这个问题专门发生在 if j.__name__ == "TurtleShape": 代码块中。基本上,出于某种原因,当用户选择撤消将海龟重置为其原始形状时,它会按原样工作直到 TurtleShape 函数由 undoHandler 执行. 出于某种原因,当 undoHandler 执行 TurtleShape 函数时,即使我为 TurtleShape 函数的 iop 属性提供了有效参数(如您在if j.__name__ == "TurtleShape": 代码块),else 语句首先被执行 (即出现文件对话框而不是从 if 语句继续)。仅当用户在该对话框中单击 cancel 时,海龟才会设置为上一张图像。

我的代码有什么问题导致了这种情况发生,我该如何阻止这种情况发生?我试过了例如,将输出保存在 undoHandler 函数中的函数中的 klob 属性更改为 "SaveImage",但仍然没有成功。我还尝试在 TurtleShape 中添加一条 if-elif 语句,当它应该在 iop 或文件对话框之间进行选择作为 klob 的值时,但问题仍然存在发生。显然,它会执行 elif 语句 ,即使它不一定为真。 因此,非常感谢任何帮助解决此问题! :)

发生在这里:

         j = i.getfunction()
         j()

如果您刚刚获得的函数是 TurtleShape() 函数,那么您将使用其默认参数(即 iop = None)调用它一次。然后你进入你的大 if j.__name__ == "TurtleShape": 语句并在 if 块中再次调用它。

j() 调用移到 if j.__name__ == "TurtleShape": 大语句的 else: 块中,您的问题就会消失。

这个简短的解释是否足以让您理解为什么会出现这个问题?或者你需要我解释一下 in-depth 调用 j() 是如何使用参数 iop = None 调用 TurtleShape?