<br><br><div class="gmail_quote">On Fri, May 20, 2011 at 10:58 AM, Michael Tobis <span dir="ltr">&lt;<a href="mailto:mtobis@gmail.com">mtobis@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

OK, but still.<br>
<br>
I have also faced this problem.<br>
<br>
Flattening nested lists which contain strings is an example.<br>
<br>
Because a string is an iterable, if we want a method that tolerates a<br>
single string or a list of strings, treating the single string the<br>
same as a list with one element, we have to be able to treat the<br>
string as a non-iterable. The question is what the most elegant way to<br>
do this is if we are building general purpose utility functions that<br>
we don;&#39;t want to violate duck typing.  I recall punting, but I also<br>
recall wondering the same thing.<br>
<br>
So, consider a routine that is intended to flatten a nested list. We<br>
want to write a recursive routine that takes [1,[2,3,[4,5],&quot;fred&quot;]] to<br>
[1,2,3,4,5,&quot;fred&quot;] and not to [1,2,3,4,5,&quot;f&quot;,&quot;r&quot;,&quot;e&quot;,&quot;d&quot;]. And even<br>
the latter is not as easy as you&#39;d expect.<br>
<br>
It totally violated least surprise for me when I did something like<br>
<br>
&gt;&gt;&gt; def atomprint(thing):<br>
...     try:<br>
...         for item in thing:<br>
...             atomprint(item)<br>
...     except TypeError:<br>
...         print thing<br>
<br>
It works beautifully for lists of integers, floats, various other<br>
things. I felt satisfied and ever so pythonic. But it overflows the<br>
stack when you pass it a non-empty string!<br></blockquote></div><br><br>matplotlib.cbook defines &quot;flatten&quot; with a scalar customizable scalarp function to do what you want (the default returns True on non-iterables and strings).  The module defines <br>

<br><br>def is_scalar_or_string(val):<br>    return is_string_like(val) or not iterable(val)<br><br>def flatten(seq, scalarp=is_scalar_or_string):<br>    &quot;&quot;&quot;<br>    this generator flattens nested containers such as<br>

<br>    &gt;&gt;&gt; l=( (&#39;John&#39;, &#39;Hunter&#39;), (1,23), [[[[42,(5,23)]]]])<br><br>    so that<br><br>    &gt;&gt;&gt; for i in flatten(l): print i,<br>    John Hunter 1 23 42 5 23<br><br>    By: Composite of Holger Krekel and Luther Blissett<br>

    From: <a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/121294">http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/121294</a><br>    and Recipe 1.12 in cookbook<br>    &quot;&quot;&quot;<br>    for item in seq:<br>

        if scalarp(item): yield item<br>        else:<br>            for subitem in flatten(item, scalarp):<br>                yield subitem<br><br><br><br>When applied to your example, it yields<br><br>In [49]: import matplotlib.cbook as cbook<br>

<br><br>In [51]: for row in cbook.flatten ([1,[2,3,[4,5],&quot;fred&quot;]] ):<br>   ....:     print row<br>   ....:<br>   ....:<br>1<br>2<br>3<br>4<br>5<br>fred<br><br><br>