On Nov 18, 1:32 am, Chris Rebert <c...@rebertia.com> wrote: > On Wed, Nov 18, 2009 at 1:15 AM, Steve Howell <showel...@yahoo.com> wrote: > > On the topic of "switch" statements and even-more-concise-then-we-have- > > already if/elif/else/end constructs, I have to say that Python does > > occasionally force you to write code like the code below. Maybe > > "force" is too strong a word, but Python lends itself to if/elif > > blocks like below, which get the job done just fine, but which are not > > syntactically pretty, due to the "(el){0,1}if kind ==" duplication. > > There are often cases where if/elif statements are just a smell that > > you do not know how to do dictionary lookups, but if you converted the > > below code to use dictionary lookups, you would complicate the code > > almost as much as you abstracted the code, if not more, unless I am > > just being very naive. > > I'm gonna have to disagree and say using the dictionary dispatch > technique would clean it up a good bit. > Yes, it would entail creating several functions, but those functions > could then be documented (vs. the currently opaque code blocks); and > due to their separation and smaller length, they would be easier to > understand and test than the given code. > Additionally, the sheer length of the given code segment probably > constitutes a code smell in and of itself for the function containing > that code. >
Here's the rewrite. The indirection from the definition of _dict to the first use of _dict is a little painful (36 lines away), but apart from that I am pleased with how the new code looks, so your points are well taken: kind = ast.kind def _dict(ast): return dictionary(ast, metavar) def _list(ast): ignore, code = dictionary(ast, 'item') code = '[%s for item in %s]' % (code, metavar) return label, code def _attr(ast): return ast.field, '%s.%s' % (metavar, ast.field) def _key(ast): return ast.field, '%s[%s]' % (metavar, repr(ast.field)) def _as(ast): ignore, parent = _code_generate(ast.parent, metavar) return ast.synonym, parent def _call(ast): parent_name, parent = _code_generate(ast.parent, metavar) parent += '()' return parent_name, parent def _recurse(ast): parent = ast.parent expr = ast.expr parent_name, parent = _code_generate(parent, metavar) kind = expr.kind if kind in ['attr', 'key', 'list']: parent_name, parent = _code_generate(expr, parent, parent_name) else: subparent_name, subparent = _code_generate(expr, parent_name) parent = '(lambda %s:\n' % parent_name + indent_block (subparent+')(%s)' % parent) return parent_name, parent dispatches = { 'dict': _dict, 'list': _list, 'attr': _attr, 'key': _key, 'as': _as, 'call': _call, 'recurse': _recurse, } if kind in dispatches: return dispatches[kind](ast) else: raise Exception('unknown kind!') Thanks! P.S. The underscores before the method names might look a little funny for inner methods, but it's the nature of the code..._dict and _list would lead to confusion with builtins, if not actual conflict. -- http://mail.python.org/mailman/listinfo/python-list