Recipe 11.2. Avoiding lambda in Writing Callback FunctionsCredit: Danny Yoo, Martin Sjogren ProblemYou need to use many callbacks without arguments, typically while writing a Tkinter-based GUI, and you'd rather avoid using lambda. SolutionBetween the classic lambda approach and a powerful general-purpose currying mechanism is a third, extremely simple way for doing callbacks that can come in handy in many practical cases: def command(callback, *args, **kwargs): def do_call( ): return callback(*args, **kwargs) # 2.4 only: do_call._ _name_ _ = callback._ _name_ _ return do_call DiscussionI remember a utility class (to perform the same task handled by a closure in this recipe) quite a while back, but I don't remember who to attribute it to. Perhaps I saw it in John E. Grayson, Python and Tkinter Programming (Manning). Writing a lot of callbacks that give customized arguments can look a little awkward with lambda, so this command closure provides alternative syntax that is easier to read. For example: import Tkinter def hello(name): print "Hello", name root = Tk( ) # the lambda way of doing it: Button(root, text="Guido", command=lambda name="Guido": hello(name)).pack( ) # using the Command class: Button(root, text="Guido", command=command(hello, "Guido")).pack( ) Of course, you can also use a more general currying approach, which enables you to fix some of the arguments when you bind the callback, while others may be given at call time (see Recipe 16.4). However, "doing the simplest thing that can possibly work" is a good programming principle (this wording of the principle is due, I believe, to Kent Beck). If your application needs callbacks that fix all arguments at currying time and others that leave some arguments to be determined at callback time, it's probably simpler to use the more general currying approach for all the callbacks. But if all the callbacks you need must fix all arguments at currying time, it may be simpler to forego unneeded generality and use the simpler, less-general approach in this recipe exclusively. You can always refactor later if it turns out that you do need the generality. See AlsoRecipe 16.4; information about Tkinter can be obtained from a variety of sources, such as Fredrik Lundh, An Introduction to Tkinter (PythonWare: http://www.pythonware.com/library), New Mexico Tech's Tkinter Reference (http://www.nmt.edu/tcc/help/lang/python/docs.html), Python in a Nutshell, and various other books. |