loops -> list/generator comprehensions

Steven Bethard steven.bethard at gmail.com
Sun Feb 6 15:03:27 EST 2005


jamesthiele.usenet at gmail.com wrote:
> I wrote this little piece of code to get a list of relative paths of
> all files in or below the current directory (*NIX):
> 
>     walkList  = [(x[0], x[2]) for x in os.walk(".")]
>     filenames = []
>     for dir, files in walkList:
>         filenames.extend(["/".join([dir, f]) for f in files])
> 
> It works fine, I don't need to change it, but I know there is a one
> liner list/generator comprehension to do this - I'm just not well
> enough versed in comprehensions to figure it out. Can someone please
> show me what it is?

I've used os.path.join instead of "/".join since it's more general, but 
other than that, this should be eqivalent:

filenames = [os.path.join(dirpath, filename)
              for dirpath, _, filenames in os.walk('.')
              for filename in filenames]


> Even better, is there a generalized way to transform simple loops into
> comprehensions that someone can point me to?

Well, generally, you need to write your loops to use an append, and then 
the translation to LC is simpler.

filenames = []
for dirpath, _, filenames in os.walk('.'):
     for filename in filenames:
         filenames.append(os.path.join(dirpath, filename))

Now that you know what it looks like with an append, you simply move the 
expression in the append to the top, and leave the fors in the same order:

filenames = [os.path.join(dirpath, filename)
              for dirpath, _, filenames in os.walk('.')
              for filename in filenames]

HTH,

STeVe



More information about the Python-list mailing list