Printing and recursion, a printer for list, tuple and dictionary
Over the time I've followed on PyPi on Twitter, there has been a number of entries regarding printing of lists. Now I know there is a pprint module and that it works well, but I decided to see if I could create a one-function printer of lists (and dictionaries as well) with the help of recursion.
Some 30 minutes later I ended up with this:
import types def printer(data, prefix='', prefix_extend=' ', sequence_types = (types.ListType, types.TupleType), dictionary_type = types.DictionaryType): if type(data) in sequence_types: for item in data: if not type(item) in sequence_types: if not type(item) == dictionary_type: print prefix, item else: printer(item, prefix=prefix+prefix_extend, prefix_extend=prefix_extend) else: printer(item, prefix=prefix+prefix_extend, prefix_extend=prefix_extend) if type(data) == dictionary_type: for key, value in data.items(): if not type(value) == dictionary_type: if not type(value) in sequence_types: print prefix, key, ':', value else: printer(value, prefix=prefix+prefix_extend, prefix_extend=prefix_extend) else: print prefix+prefix_extend, key, ':' printer(value, prefix=prefix+prefix_extend+prefix_extend, prefix_extend=prefix_extend) data = [1,2,3, [4,5, [6,7] ], {'a':1, 'b':{'c':3, 'd':{1:1}}}] printer(data)
And the output is what you'd expect:
1 2 3 4 5 6 7 a : 1 b : c : 3 d : 1 : 1
Now, if you're working with deeply nested sequences and dictionaries, it might be an idea to go more object oriented.. but that depends. d:]
Any better ones?
[Permalink] [By morphex] [Python-only or > 0.5 Python related (Atom feed)] [2012 29 Jul 14:33 GMT+2]
Comments
Ŵut?By: Jul Simplest way: python -c 'print(__import__("json").dumps(dict( a= "b", c= { "d" : [ 1, 2, 3 ] }),indent=4))' But first «nested printer module» are not something useful since we have no need for them, and secondly you miss the whole point: http://blog.aclark.net/2012/05/23/a-simple-printer-of-nested-lists/ |
Better?By: shiihs What property in your opinion would make it *better* ? Handling more/different data types? Shorter code? Faster code? Python 3.X compliance? ... |
WellBy: obernard I agee with shiihs: what is better? Nevertheless, I have some comments. ^^ Why put sequence_types and dictionary_type in arguments of printer? To have the possibility to change them? Well, in this case, what do they become at the first recursion call? When I use a function called printer (even though I'm more used to verbs instead of names for functions), I'm waiting for it to print anything. I'm pretty sure that, in this case, calling printer(42) or printer('spam') will leave me greatly disappointed. Oh, and anything is better with a docstring. ;) |
Faster, better, strongerBy: Morten W. Petersen Jul, I see Alex has also noticed the nested list printer, I didn't know of that post but yeah OK. I was thinking about these PyPi people yesterday and about list printers and thought I'd start a discussion and then put it to rest. shiihs, faster code maybe. I thought of this as an exercise in recursive code and also just a test to see where my form and code expertise is at these days. obernard, yeah this thing was thrown together in 30 minutes so it wasn't extensively tested. Making the second main if an elif and tacking this onto the end of the main if block: else: print prefix, str(data) fixes the printer(42). :) The sequence_types and dictionary_type arguments are there as a speed optimization as opposed to defining the variables globally or every time the function is called. Docstring? Again, just threw it together. I trust you will put one in if you want to include it somewhere ;) |
tail recursion + isinstanceBy: jtayon For your nested printer I would use http://www.python.org/dev/peps/pep-3119/ => from collections.abc import Mappings And I would use a tail recursion this way https://github.com/jul/archery/blob/master/archery/barrack.py#L19 With this code I can do >>> print("\n".join([ "->".join(map(str,x[:-1])) + ":%s" % x[-1] for x in mapping_row_iter({ 'a' : { 'b' : 1 }, 'c': {frozenset( ["a", 1]) : 23} }) ])) a->b:1 c->frozenset(['a', 1]):23 My representation is not the usual nested printer list but it is more compact, and focus on the path to key information. I uses this piece of code more often than the usual view since I can easily map a nest lists of lists to a CSV this way. |
Interesting exampleBy: Morten W. Petersen jtayon, that was an interesting example. I haven't used sets much so I'll play around when I get the time and respond here. |