Miscellaneous design and Python use questions

Tim Peters tim_one at email.msn.com
Fri Feb 18 03:00:11 EST 2000


[Gordon McMillan]
> You'll probably be happier if you stop thinking in strict OO
> terms, and realize that Python is all about interfaces, and
> interfaces are implicit (no need to inherit from some particular
> base class). To paraphrase Aahz: loosely couple, and
> componentize the hell out of everything.

[Travis B. Hartwell]
> What exactly do you mean by interfaces here?  I think I understand
> what your paraphrasing meant:  Don't have your classes / modules /
> whatever tied too tightly together (i.e., a good example of
> information hiding) and make everything very indepedent.  Is that
> right?

It's a bit hard to explain, because although interfaces are vital to True
Python Practice, there's no syntax in the language that supports interfaces
directly!  It has the flavor of folklore as a result.

For example, the Reference Manual talks about "sequence types" and "mapping
types", and they're fundamental tools.  However, search as you will, there
*isn't* any "sequence type" thingie visible at the Python level, or even at
the implementation level.  Whether an object "acts like a sequence" depends
on whether it supports things like indexing (== its class has a __getitem__
method).  There's nothing either rigid or enforced about it, though, and you
can very often just add some simple method to a class to get it to "act
enough like a sequence" to pass to a function that requires a sequence
argument.

Another example:  The "file-like object" interface is also informal and
widespread -- in most cases, functions that require files are perfectly
happy if you pass them anything whatsoever with "readline" and/or "write"
methods.

In small systems this is overwhelmingly a blessing, letting you change
things around radically and rapidly with surprisingly little breakage.
Maybe we can twist your head in the appropriate direction by saying you
shouldn't worry about an object's *class* (or type) so much as what an
object can "do" (which methods it supports).  It's a subtle distinction, and
the most generally useful Python code doesn't contain

    if isinstance(somearg, FrobnicatorClass):

but

    if hasattr(somearg, "fronbicate"):

As systems get larger and more complex, though, relying on folklore
interfaces gets less attractive.  There's nothing wrong (& much right!) with
*eventually* defining a FrobnicatorClass mixin and deriving frobnicators
from it, but if you do that from the start you freeze decisions too early.

Which is maybe a deeper hint:  refactoring, e.g., C++ code is an utter pain
in the ass, so people tend to be reluctant to "just try something" in C++.
You're getting the hang of writing True Python when you think nothing of
rewriting your whole class hierarchy five times.  So long as you rely on
implicit interfaces, then e.g. moving ".frobnicate(self, other)" from class
A to class B  is a single cut-and-paste, so there's little pain in pursuing
a promising rearrangement (neither in retracting it later when it proves to
suck bigtime <wink>).

the-measure-of-a-good-python-programmer-is-how-much-of-their-
    code-they-throw-away-without-regret-ly y'rs  - tim






More information about the Python-list mailing list