[Python-3000] ABC's, Roles, etc
Phillip J. Eby
pje at telecommunity.com
Sat May 12 20:29:17 CEST 2007
At 11:58 AM 5/12/2007 -0600, Jeff Shell wrote:
>Actually, I don't know what LBYL and EFTP (or whatever that other one
>is) mean in this context. This is the first time I've heard, or at
>least paid attention to, those acronyms. In this context anyways.
>If you could explain what this really means, and KTATAM (Keep The
>Acronyms To A Minimum), I would appreciate it. I recognize the
>arguments I've made seem to go behind LBYL, but that was mostly chosen
>because that's what you said zope.interface did or was. And
>gul-darnit, I like zope.interface.
Checking whether an object provides an interface is LBYL. Simply
proceeding as if it does (or adapting it to a desired interface), is EAFP.
zope.interface can certainly be used in either style, but when it was
first created, LBYL is *all* it did. Adaptation was added later.
> > Well, "back in the day", before PyProtocols was written, I discovered
> > PEP 246 adaptation and began trying to convince Jim Fulton that
> > adaptation beat the pants off of using if-then's to do "implements"
> > testing. His argument then, IIRC, was that interface verification
> > was more important. I then went off and wrote PyProtocols in large
> > part (specifically the large documentation part!) to show him what
> > could be done using adaptation as a core concept.
>I think it's beneficial to have both. But I agree, it's usually better
>to program against adaptation. It provides more flexibility. I think
>the 'hasattr()' syndrome still hangs over many of us, however. We're
>used to looking at the piece of the duck we're interested in more than
>trying to see if we can put something into a duck suit (or better yet
>- Duck Soup!)
>But the 'provides / provided by' piece is still important to me.
>Adaptation isn't *always* needed or useful.
That's actually an illusion created by the economic impact of using
interfaces and adapters instead of generic functions. In languages
with generic functions, nobody bothers creating separate "trait"
systems, apart from designating groups of GFs that "go
together". (Haskell typeclasses and Dylan modules, for example),
because GFs are so easy and elementary that it seems like part of the
normal development flow.
Interfaces+Adaptation are such a clumsy way of doing the same thing,
that it often seems easier to get by *checking* for an existing
interface, instead of defining a new one and adapting to it. (Or
just using an overload.)
But in the early days of PyProtocols, I soon realized that checking
for an interface was *always* an antipattern, no matter how
temptingly convenient it might appear to be to rationalize an
interface check at the time. You can get away with it
sometimes... but never for long, if your code is being reused.
>I don't know if that's LBYL, EYV (Eat Your Vegetables), LBWBCTS (Look
>Both Ways Before Crossing The Street), or what. I think it's just a
>way of saying "I happen to know that this thing smells like a duck. It
>doesn't say that it smells like a duck, but I know it smells like a
>duck. And for everywhere that I expect to find the fine fragrance of
>duck, this thing should be allowed."
Note that this is still one level of abstraction away from your goal:
to get some behavior. Instead of checking for duckness or
quackability, *just peform the "quack" operation*.
If you want to know about quackability because you intend to do
something *else* with the object, then just do that "something else".
The point of generic functions is that the only reason it's worth
knowing something about a "trait" is to select *how* you will
accomplish something. So just accomplish the something, instead of
Remember the bad old days before OO? The big step forward was to get
rid of all those switch/cases in your functions, replacing them with
method dispatching. The second big step forward is to get rid of the
type/hasattr/interface/role/trait testing, and replace it with
More information about the Python-3000