The way I do it is like this:
In the __init__ method set up handlers for the wx.EVT_CLOSE event and a menu item that is your "real" quit option. You need this or you can never close your program.
def OnClose(self,evt):
#Turn closes into hides unless this is a quit application message / or OS shutting down
if evt.CanVeto():
self.Hide()
evt.Veto()
else:
#if we don't veto it we allow the event to propogate
evt.Skip()
def OnMenuExit(self,evt):
#Event handler for exit menu item
self.Close(force=True) #Stops the close handler vetoing it
You should also make sure that in __init__ you call wx.App.SetMacExitMenuItemId( [ID OF YOUR EXIT MENU ITEM HERE] ) so that the quit item in your dock context menu routes to your correct menu handler.
This gives you a nice mac-ish hide when the window is closed. You need to be aware that the app is still runnning and its menus can be called as the menu bar is still in the top of the screen. Strategic calls to self.Show() in menu event handlers are your friend here.
You can also make good use of wx.TaskBarIcon to interact nicely with the dock when your app window is hidden (e.g. click on dock to reshow window).