KBD

Keith Devens .com

Wednesday, July 9, 2008 Flag waving
All warfare is based on deception. – Sun Tzu (The Art of War (I.18))
← Comictastic: Comic Viewing Like CrazyOutlook easter egg →

Daily link icon Friday, December 2, 2005

Unusual Python list comprehensions

I needed to write a little code that would grab the filenames of all zip files out of a directory hierarchy. I immediately tried to write it as a big list comprehension and completely failed. So, I backed off a step to the following (some code in this post refomatted to not break my layout):

finalfiles = []
for (dir, subdirs, files) in os.walk("c:/temp/"):
    finalfiles.extend([
        os.path.join(dir, file)
        for file in files if file.lower().endswith(".zip")
    ])

I took a look at the list comprehension examples in the Python quick reference to figure out why I was having a problem. Here is their reference code (the two blocks are equivalent):

result = [expression for item1 in sequence1  if condition1
             for item2 in sequence2 ... for itemN in sequenceN
         ]

result = []
for item1 in sequence1:
    for item2 in sequence2:
        ...
        for itemN in sequenceN:
            if (condition1) and further conditions:
               result.append(expression)

So, first I converted my finalfiles.extend() to an append() form:

finalfiles = []
for (dir, subdirs, files) in os.walk("c:/temp/"):
    for file in files:
        if file.lower().endswith(".zip"):
            finalfiles.append(os.path.join(dir,file))

so that I could directly translate from the nested loop version to the list comprehension version, essentially doing textual substitution of item1, expression, and so on.

After doing the substitution, this is what you wind up with:

finalfiles = [
    os.path.join(dir,file)
    for (dir, subdirs, files) in os.walk("c:/temp/")
    for file in files if file.lower().endswith(".zip")
]

That seems backwards to my brain, which is why I didn't get it right the first time. I think this is really a case where doing a list comprehension is not clearer than doing at least part of it in a normal loop fashion.

Note: my brain feels like it should be this way:

finalfiles = [
    os.path.join(dir,file)
    for file in files if file.lower().endswith(".zip")
    for (dir, subdirs, files) in os.walk("c:/temp/")
]

which corresponds rather to:

result = [expression for item2 in sequence2
    for item1 in sequence1
]

I think that makes more sense. Which fits your brain?

← Comictastic: Comic Viewing Like CrazyOutlook easter egg →

Comments XML gif

DJ Hannibal wrote:

This is the way it should I think it be:

finalfiles = [
os.path.join(dir,file)
for file in files if file.lower().endswith(".zip")
for (dir, subdirs, files) in os.walk("c:/temp/")
]

∴ DJ Hannibal | 2-Dec-2005 10:21am est | #8783

David wrote:

As a Python newbie, list comprehensions make my head asplode.

∴ David | 11-Dec-2005 12:15am est | #8830

Feel free to post a comment below. Please see my comment policy.

Formatting Rules (No HTML):

  • **bold**, *italic*, _underlined_, --strikeout--
  • "text"="url" creates a link, and URLs are auto-highlighted
  • Blockquote: Like e-mail, begin paragraph with > (greater-than sign)
  • Lists: begin paragraph with *,-, or + (unordered), or # (ordered)
  • Code block: ?!code:language=perl|php|sql|javascript|etc.{\n}...{\n}?!/code

:
(will be your IP address if blank)
: (optional)
(Will not be shown on site)

: (optional)
:

July 2008
SunMonTueWedThuFriSat
 12345
6789101112
13141516171819
20212223242526
2728293031 



RSS feed RSS feed for Keith's Weblog
Atom feed Atom feed for Keith's Weblog
Weblog archive
Recent comments
  on 2 posts

Recent comments XML

getElementsByClass function

http://pitfalls.wordpress.com/2008/​07/07/querying-it-jquery-way-getele​ments...

maxgandalf: Jul 7, 5:50am

Generated in about 0.351s.

(Used 8 db queries)

mobile phone