A simple but useful class that emulates a function to gracefully permit latent assignment. In other words, I can use the emulating class as a valid function in assignments with the ability to later associate a function to perfrom the actual operations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
# This is the emulating class. class Function: def __init__(self): # Dummy function self.function = lambda *args:None self.menu = None self.button = None self.enabled = True # This method causes the Function instances to be # callable as though they were a function def __call__(self, *args): if self.enabled: return self.function(*args) def SetFunction(self, func): self.function = func def SetMenu(self, menu): self.menu = menu self.menu.Enable(self.enabled) def SetButton(self, btn): self.button = btn self.button.Enable(self.enabled) def Enable(self, on=True): if self.menu: self.menu.Enable(on) if self.button: self.button.Enable(on) self.enabled = on class FUNCTION_TABLE: NewFile = Function() OpenFile = Function() SaveFile = Function() Exit = Function() ... # Initializing the main wx.Frame... item = wx.MenuItem( menu, id, "&Open", "Open a file" ) # Note that OpenFile will act as an event handler, but at this # moment, no function has actually been assigned to handle the event self.Bind( wx.EVT_MENU, FUNCTION_TABLE.OpenFile, id=id ) FUNCTION_TABLE.OpenFile.SetMenu( item ) ... # Populating a wx.Panel (or similiar object) with controls, etc... button = wx.Button( self, id, "Open File" ) button.Bind( wx.EVT_BUTTON, FUNCTION_TABLE.OpenFile ) FUNCTION_TABLE.OpenFile.SetButton( button ) # A function is finally assigned, but nobody is any the wiser. # My button and my menu are still going to call the same thing. # They don't know anything about self.OnOpenFile, nor do they # need to. They also don't know about each other! FUNCTION_TABLE.OpenFile.SetFunction( self.OnOpenFile ) ... # An event handler method of the wx.Panel... def OnOpenFile(event): ...
Using wxPython, I have multiple GUI controls accessing the same event handler. In this example, a menu item and a button both perform the same file opening operation. Unfortunately, the menu is defined well before the panel with the button (and hence the event handler) is defined.
Using this function table, I am able to give the menu item something to Bind to that I can later assign a function to when my panel is defined. This way my menu definition doesn't need to know anything about my button, and vice versa. Each definition independently registers itself.
Another great benefit is the ability to tie these elements together in other ways. Continuing with the menu and button example, I can enable/disable both of them through the same class. By making FUNCTION_TABLE visible throughout my program, I can easily enable/disable all controls associated with opening files without having to be able to see any particular control. How wonderful is this!?!
Though I came across this emulation trick independently, I am sure it is not novel in the Python community. I trust, however, that my example application of it will still be educational nonetheless.
Factorization recommended. Hi. I'd recommend that methods like setMenu() should be added to a specialization of Function class instead of the class itself. That should improve the reuse of Function class.