views:

157

answers:

2
button1 = tkinter.Button(frame, text="Say hi", command=print)
button2 = tkinter.Button(frame, text="foo", command=print)
button3 = tkinter.Button(frame, text="bar", command=print)

You've probably spotted the hole in my program: print can't specify arguments. This renders the whole thing useless and faulty. Obviously, having something like

command=print("foo")

will call that function when the object is actually instantiated and make command the return value (if any) of that function call. (Not what I want)

So, how can I specify arguments in the above mentioned scenario, and avoid having to define seperate command functions for each of the buttons?

+3  A: 

If you have at least python 2.6 (which I'm guessing you are since you use print in a function position) you can use functools.partial. It takes a function and any arguments to supply and returns a callable that will call the underlying function and add on any arguments passed to the final call. For example:

>>> from functools import partial
>>> def add(x,y): return x+y
>>> add2 = partial(add,2)
>>> add3 = partial(add,3)
>>> add2(3)
5
>>> add3(5)
8

Your example could be done as

from functools import partial
button1 = tkinter.Button(frame, text="Say hi", command=partial(print,"hi"))
button2 = tkinter.Button(frame, text="foo", command=partial(print,"foo"))
button3 = tkinter.Button(frame, text="bar", command=partial(print,"bar"))

If you don't have 2.6, you can implement partial as:

def partial(fun, *args, **kwargs):
  def merge(d1,d2):
    r = dict(d1)
    r.update(d2)
    return r
  return lambda *a,**kw: fun(*(args+a),**(merge(kwargs,kw)))
Geoff Reedy
Now, add the `lambda` alternative for older pythons and your answer should be chosen.
ΤΖΩΤΖΙΟΥ
+1  A: 

You could use lambda expressions: http://www.bembry.org/technology/python/notes/tkinter_4.php

Ofir