[Python-ideas] An illustrative example for PEP 3150's statement local namespaces

Nick Coghlan ncoghlan at gmail.com
Thu Oct 20 06:37:16 CEST 2011


A task I actually ran into at work this week: get a filtered list of
subdirectories, exclude some based on a list of names to be ignored,
sort the remainder by their modification times.

(This problem was actually also the origin of my recent filter_walk
recipe: http://code.activestate.com/recipes/577913-selective-directory-walking/)

Translated to 3.x (i.e. the generator's .next() method is replaced by
the next() builtin), the code would look roughly like this:

    # Generate list of candidate directories sorted by modification time
    candidates = next(filter_walk(base_dir, dir_pattern=dir_filter,
depth=0)).subdirs
    candidates = (subdir for subdir in candidates if not any(d in
subdir for d in dirs_to_ignore))
    def get_mtime(path):
        stat_path = os.path.join(base_dir, path)
        return os.stat(stat_path).st_mtime
    candidates = sorted(candidates, key=get_mtime)

Now, that could theoretically be split out to a separate function
(passing base_dir, dir_filter and dirs_to_ignore as arguments), but
the details are going to vary too much from use case to use case to
make reusing it practical. Even factoring out "get_mtime" would be a
waste, since you end up with a combinatorial explosion of functions if
you try to do things like that (it's the local code base equivalent of
"not every 3 line function needs to be in the standard library").

I can (and do) use vertical white space to give some indication that
the calculation is complete, but PEP 3150 would allow me to be even
more explicit by indenting every step in the calculation except the
last one:

    candidate_dirs = sorted(candidate_dirs, key=get_mtime) given:
        candidate_dirs = next(filter_walk(base_dir,
dir_pattern=dir_filter, depth=0)).subdirs
        candidate_dirs = (subdir for subdir in candidates if not any(d
in subdir for d in dirs_to_ignore))
        def get_mtime(path):
            stat_path = os.path.join(base_dir, path)
            return os.stat(stat_path).st_mtime

Notice how the comment from the original version becomes redundant in
the second version? It's just repeating what the actual header line
right below it says, so I got rid of it. In the original version it
was necessary because there was no indentation in the code to indicate
that this was all just different stages of one internal calculation
leading up to that final step to create the sorted list.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia



More information about the Python-ideas mailing list