3rd argument to os.path.walk(): Why?
Alex Martelli
aleaxit at yahoo.com
Tue Dec 12 04:12:56 EST 2000
"Rob Hooft" <rob at hooft.net> wrote in message
news:m2vgsqw1k2.fsf at hooft.net...
>
> AM> E.g., say you want to _count_ the files:
>
> AM> import os
>
> AM> class Counter:
> AM> def __init__(self):
> AM> self.count = 0
> AM> def inc(self, n=1):
> AM> self.count += n
>
> AM> def count_names(count, dir, flist):
> AM> count.inc(len(flist))
>
> AM> count = Counter()
> AM> os.path.walk("/", count_names, count)
>
> AM> print count.count,"files in all"
>
> If you'd do this, why not make "count_names" a method of the Counter
> class?
As things stand here, "Counter" is a completely general-purpose
class, which has no knowledge whatsoever of files, their names,
and path-walking -- it's completely decoupled from all of these
concerns, a low-level "utility class" that is reusable in all
sorts of contexts.
Strictly coupling a generic counter-class to specific things it
could be counting doesn't seem like an elegant design at all.
If anything, one might *derive* from Counter a NamesCounter
subclass, or *contain and delegate-to* a Counter from a wrapper
class -- assuming os.path.walk takes any callable (specifically,
a bound method is what we would pass here) even though the docs
specifically say it takes a *function* instead (the docs are
often too-restrictive regarding object-types expected by core
Python functions...).
Once that is feasible, then both idioms for setting callbacks
are equally elegant:
1. the classical procedural set-callback idiom, where you
provide a function (typically not carrying state) and
the state to be passed to it as an argument when the
calling-back does happen;
2. the strongly object-oriented set-callback idiom, where
you provide a callable object which entirely takes care
of its own state issues.
The tradeoffs between these two design approaches are,
more or less, 'the usual suspects'. One way to frame [1]
is strictly object-oriented terms is as an application
of the "Memento" design-pattern -- the 'function' might
still be a more-general 'callable', but some part of its
state is objectified as a separate 'memento' object that
is explicitly handled back to it as needed.
"Memento" is one of many important ways in which issues
of object-identity and object-state can be decoupled, and
thereby handled more explicitly, with finer-grained
control. (One doesn't always _want_ to control things
on a fine-grained level, which is why it's nice to have
different idioms available in the language/framework:-).
Alex
More information about the Python-list
mailing list