There are situations in Python code when a function is used as an object rather then a function call. Handling arguments becomes a mild problem, that can easily be handled by wrapping the function object and its arguments. One common way is the use of a curry function or class. This snippet shows the use of a curry function in a short Tkinter GUI dialog demo. Here the function objects appear in a dictionary of dialogs and the button command associated with a specific dialog.
Adding Arguments to Function Objects with Curry (Python)
# use Tkinter to create a series of buttons that associate with dialog objects
# handle arguments to and from the dialog objects with function curry()
# tested with Python24 vegaseat 19sep2006
from Tkinter import *
from tkFileDialog import askopenfilename
from tkMessageBox import askquestion, showerror, askokcancel
from tkSimpleDialog import askfloat, askinteger, askstring
from tkColorChooser import askcolor
root = Tk()
# most efficient generic function for currying
def curry(fn, *cargs, **ckwargs):
def call_fn(*fargs, **fkwargs):
d = ckwargs.copy()
d.update(fkwargs)
return fn(*(cargs + fargs), **d)
return call_fn
# since this is a dictionary, buttons pack in a hashed order
# the dictionary uses function objects so you have to wrap the object and its arguments
dialogs = {
'Open': askopenfilename, # returns eg. D:/Python24/Atest/tk/Tk_DialogDemo1.pyw
'Color': askcolor, # returns eg. ((0, 0, 255), '#0000ff') if you picked color blue
'Question': curry(askquestion, 'Warning', 'Erase zz.txt file?'), # returns 'yes' or 'no'
'Error': curry(showerror, 'showerror', "Stupid error!"), # returns 'ok'
'Input_F': curry(askfloat, 'askfloat', 'Enter price of petrol'), # returns floating point value
'Input_I': curry(askinteger, 'askinteger', 'Enter your age'), # returns an integer value
'Input_S': curry(askstring, 'askstring', 'Enter your name'), # returns a string
'Query': curry(askokcancel, 'askokcancel', 'Okay to proceed?') # returns True or False (1 or 0)
}
class MyApp(Frame):
"""create a frame with two labels and a series of buttons"""
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.pack()
self.label1 = Label(self, text="Click to bring up dialog")
self.label1.pack()
for (key, value) in dialogs.items():
# sets up the button and associates the proper dialog object
callback = curry(self.dialog_result, name=key)
Button(self, text=key, command=callback).pack(side=TOP, fill=BOTH)
Button(self, text='Quit', command=root.destroy).pack(side=TOP, fill=BOTH)
self.label2 = Label(self, text="result", bg='yellow')
self.label2.pack()
def dialog_result(self, name):
# connect dialog name/key with its result
result = dialogs[name]()
# show result in label2
self.label2.config(text=result)
# to test, set label1 background to the color you picked
if name == 'Color':
color = result[1] # uses hex_color = dialogs['Color']()[1]
self.label1.config(bg=color)
if __name__ == '__main__':
app = MyApp()
app.mainloop()
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.