问题
I'm using Tkinter for a simple trivia game. There are several buttons, one for each answer, and I'd like to run a checkAnswer function with certain parameters when one is clicked.
If I used something like the following:
self.option1 = Button(frame, text="1842", command=self.checkAnswer(question=3, answer=2))
Then it would run checkAnswer and use what it returned (nothing).
Is there a simple way to store the parameters in the button constructor?
回答1:
This is exactly what functools.partial() is designed to do:
>>> import functools
>>> print_with_hello = functools.partial(print, "Hello")
>>> print_with_hello("World")
Hello World
>>> print_with_hello()
Hello
partial()
returns a new function that behaves just as the old one, but with any arguments you passed in filled, so in your case:
import functools
...
self.option1 = Button(frame, text="1842", command=functools.partial(self.checkAnswer, question=3, answer=2))
回答2:
You could create a higher order function to wrap your checkAnswer
function. This would allow you to return a function that wouldn't require any parameters, and therefore could be used as a callback.
For example:
def makeCheckAnswer(self, **kwargs)
return lambda: self.checkAnswer(**kwargs)
This would make your button initialization:
self.option1 = Button(frame, text="1842", command=self.makeCheckAnswer(question=3, answer=2))
回答3:
By far easiest is just to use lambda in place
self.option1 = Button(frame, text="1842",
command=lambda: self.checkAnswer(question=3, answer=2))
Though, in a similar but a bit more complicated cases, you really should use a function factory such as
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))
because it would make sure that you pass in correct arguments (not quetsion
(sic) for example); notice the difference from functools.partial
which allows you to mistype the function arguments and get an exception only when clicked on the button ;)
Also, hardcoding the questions / answers in the button code does not seem right...
回答4:
If you have functions that have specific parameters (that dont rely on things like text.get()
) you can use wrappers for it, which would be the easiest way to do this, other than lambada functions. For example:
def option1wrapper():
ClassName.checkAnswer(question=3,answer=2)
self.option1 = Button(frame, text="1842", command=option1wrapper)
来源:https://stackoverflow.com/questions/10692602/python-store-function-with-parameters