For interest - an extended version of the example. I have included a certain amount of magic that can lead you to a deeper understanding of Python!
And - as I am always happy to continue to study - does anyone else have any suggestions on how this should be expanded and improved in the correct pythonic manner?
class MenuItem(object): def __init__(self, fn, descr=None, shortcuts=None): """ @param fn: callable, callback for the menu item. Menu quits if fn returns False @param descr: str, one-line description of the function @param shortcuts: list of str, alternative identifiers for the menu item """ if hasattr(fn, '__call__'): self.fn = fn else: raise TypeError('fn must be callable') if descr is not None: self.descr = descr elif hasattr(fn, '__doc__'): self.descr = fn.__doc__ else: self.descr = '<no description>' if shortcuts is None: shortcuts = [] self.shortcuts = set(str(s).lower() for s in shortcuts) def __str__(self): return self.descr def hasShortcut(self,s): "Option has a matching shortcut string?" return str(s).lower() in self.shortcuts def __call__(self, *args, **kwargs): return self.fn(*args, **kwargs) class Menu(object): def __init__(self): self._opts = [] def add(self, od, *args, **kwargs): """ Add menu item can be called as either .add(MenuItem) .add(args, to, pass, to, MenuItem.__init__) """ if isinstance(od, MenuItem): self._opts.append(od) else: self._opts.append(MenuItem(od, *args, **kwargs)) def __str__(self, fmt="{0:>4}: {1}", jn='\n'): res = [] for n,d in enumerate(self._opts): res.append(fmt.format(n+1, d)) return jn.join(res) def match(self, s): try: num = int(s) if 1 <= num <= len(self._opts): return self._opts[num-1] except ValueError: pass for opt in self._opts: if opt.hasShortcut(s): return opt return None def __call__(self, s=None): if s is None: s = getStr(self) return self.match(s) def fahr_cels(f): """ @param f: float, temperature in degrees Fahrenheit Return temperature in degrees Celsius """ return (f-32.0)/1.8 def cels_fahr(c): """ @param c: float, temperature in degrees Celsius Return temperature in degrees Fahrenheit """ return (c*1.8)+32.0 def getFloat(msg=''): return float(raw_input(msg)) def getStr(msg=''): print(msg) return raw_input().strip() def doFahrCels(): "Convert Fahrenheit to Celsius" f = getFloat('Please enter degrees Fahrenheit: ') print('That is {0:0.1f} degrees Celsius'.format(fahr_cels(f))) return True def doCelsFahr(): "Convert Celsius to Fahrenheit" c = getFloat('Please enter degrees Celsius: ') print('That is {0:0.1f} degrees Fahrenheit'.format(cels_fahr(c))) return True def doQuit(): "Quit" return False def makeMenu(): menu = Menu() menu.add(doFahrCels, None, ['f']) menu.add(doCelsFahr, None, ['c']) menu.add(doQuit, None, ['q','e','x','quit','exit','bye','done']) return menu def main(): print("Welcome to the NetBeans Temperature Converter.") menu = makeMenu() while True: opt = menu() if opt is None:
Hugh bothwell
source share