Nidelven IT - All about Python, Zope & Plone - and Open Source!

Here you'll find issues related to our services. Mostly about Python, Zope and Plone, as well as hosting-related issues.

"Keeping IT real"






Older entries



Atom - Subscribe - Categories
Previous | Next

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? ...

Well

By: 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, stronger

By: 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 + isinstance

By: 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 example

By: 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.


Add comment (text format)

Passphrase

A passphrase is required to comment on this weblog. It is required to make sure that bots aren't doing automatic spamming. It is: nit is the best!.

Title

Name

Email

Comment