[Tutor] Button command arguments: Using class to wrap function call versus using lambda in tkinter

boB Stepp robertvstepp at gmail.com
Sun Apr 23 01:02:48 EDT 2017


Phil's recent postings have motivated me to try studying tkinter more
systematically starting today, so I have been looking over available
web resources.  Playing around with the code in one such resource, I
was looking at a section entitled "Arguments to Callbacks" towards the
bottom of the page at

http://userpages.umbc.edu/~dhood2/courses/cmsc433/spring2012/?section=Notes&topic=Python&notes=92

they have the code snippet:

==========================================================================
import Tkinter


# command class to wrap function call with args
# a.k.a. "currying"
class Command:
    def __init__(self, callback, *args, **kwargs):
        self.callback = callback
        self.args = args
        self.kwargs = kwargs

    def __call__(self):
        return apply(self.callback, self.args, self.kwargs)


def callback(arg):
    print "You called callback with the following arg: %s" % arg


root = Tkinter.Tk()

Tkinter.Button(root, text="Foo", command=Command(callback, 'Foo')).pack()
Tkinter.Button(root, text="Bar", command=Command(callback, 'Bar')).pack()
Tkinter.Button(root, text="Baz", command=Command(callback, 'Baz')).pack()

root.mainloop()
==========================================================================

This is Python 2 code, so I endeavored to convert it to Python 3.  I
came up with:

==========================================================================
#!/usr/bin/env python3

import tkinter as tk

# Command class to wrap function call with args
# A.K.A. "currying"
class Command:
    def __init__(self, callback, *args, **kwargs):
        self.callback = callback
        self.args = args
        self.kwargs = kwargs

    def __call__(self):
        return self.callback(*self.args, **self.kwargs)

def callback(arg):
    print('You called callback with the following arg:  %s' % arg)

root = tk.Tk()
tk.Button(root, text='Foo', command=Command(callback, 'Foo')).pack()
tk.Button(root, text='Bar', command=Command(callback, 'Bar')).pack()
tk.Button(root, text='Baz', command=Command(callback, 'Baz')).pack()

root.mainloop()
==========================================================================

This seems to work fine, and got me to wondering about using lambda
instead of this class wrapper approach, which gave me:

==========================================================================
import tkinter as tk

def callback(arg):
    print('You called callback with the following arg:  %s' % arg)

root = tk.Tk()
tk.Button(root, text='Foo', command=lambda arg='Foo': callback(arg)).pack()
tk.Button(root, text='Bar', command=lambda arg='Bar': callback(arg)).pack()
tk.Button(root, text='Baz', command=lambda arg='Baz': callback(arg)).pack()

root.mainloop()
==========================================================================

And this also works well.  Seeing as this approach has fewer lines of
code and reads clearly, what advantages would the class wrapper
approach have?  The only thing that is occurring to me in my current
sleepy state is that the class wrapper is much more flexible with
handling varying passed arguments.  Are there other considerations I
should be aware of?

As usual, many thanks in advance!

Cheers!


-- 
boB


More information about the Tutor mailing list