【问题标题】:Python - Store function with parametersPython - 带参数的存储函数
【发布时间】:2012-05-21 21:04:36
【问题描述】:

我正在使用 Tkinter 进行简单的琐事游戏。有几个按钮,每个答案一个,我想在单击一个时运行带有某些参数的 checkAnswer 函数。

如果我使用类似以下的内容:

self.option1 = Button(frame, text="1842", command=self.checkAnswer(question=3, answer=2))

然后它将运行 checkAnswer 并使用它返回的内容(无)。

有没有简单的方法在按钮构造函数中存储参数?

【问题讨论】:

    标签: python tkinter


    【解决方案1】:

    这正是functools.partial() 的设计目的:

    >>> import functools
    >>> print_with_hello = functools.partial(print, "Hello")
    >>> print_with_hello("World")
    Hello World
    >>> print_with_hello()
    Hello
    

    partial() 返回一个新函数,其行为与旧函数一样,但您传入的任何参数都已填充,因此在您的情况下:

    import functools
    
    ...
    
    self.option1 = Button(frame, text="1842", command=functools.partial(self.checkAnswer, question=3, answer=2))
    

    【讨论】:

      【解决方案2】:

      您可以创建一个高阶函数来包装您的 checkAnswer 函数。这将允许您返回一个不需要任何参数的函数,因此可以用作回调。

      例如:

      def makeCheckAnswer(self, **kwargs)
          return lambda: self.checkAnswer(**kwargs)
      

      这将使您的按钮初始化:

      self.option1 = Button(frame, text="1842", command=self.makeCheckAnswer(question=3, answer=2))
      

      【讨论】:

      • 我不会 -1,但这是在重新发明轮子。 functools.partial() 这样做。
      • 这很简洁,也是一个更好的解决方案。谢谢!
      【解决方案3】:

      目前最简单的就是使用 lambda

      self.option1 = Button(frame, text="1842", 
          command=lambda: self.checkAnswer(question=3, answer=2))
      

      虽然,在类似但稍微复杂一点的情况下,您确实应该使用诸如

      之类的函数工厂
      def answerCheckerFactory(self, question, answer):
          def checker():
              return self.checkAnswer(question, answer)
      
          return checker
      
          ...
          self.option1 = Button(frame, text="1842", 
              command=self.answerCheckerFactory(question=3, answer=2))
      

      因为它会确保您传递正确的参数(例如,不是 quetsion (sic));注意与functools.partial 的区别,它允许您错误输入函数参数并仅在单击按钮时获得异常;)

      此外,在按钮代码中硬编码问题/答案似乎不正确...

      【讨论】:

      • 我完全不同意,这不太清楚,重新发明轮子。
      • 我不会硬编码它,这只是一个例子。我也不介意我是否遇到延迟异常。
      【解决方案4】:

      如果您有具有特定参数的函数(不依赖于 text.get() 之类的东西),您可以为其使用包装器,这将是执行此操作的最简单方法,而不是 Lambada 函数。例如:

      def option1wrapper():
          ClassName.checkAnswer(question=3,answer=2)
      self.option1 = Button(frame, text="1842", command=option1wrapper)
      

      【讨论】:

        【解决方案5】:

        只有你需要使用这样的 lambda 函数

        self.option1 = lambda: Button(frame, text="1842", command=self.checkAnswer(question=3, answer=2))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-12-08
          • 2020-02-12
          • 1970-01-01
          • 1970-01-01
          • 2022-12-17
          相关资源
          最近更新 更多