How about "pure virtual methods"?

Alex Martelli aleaxit at yahoo.com
Sun Dec 19 16:10:40 CET 2004


John Machin <sjmachin at lexicon.net> wrote:
   ...
> 6. Alex's magnum opus appears to operate on problem a, and maybe on b
> (it's over my head). It involves a fair chunk of mucking about -- for

A dozen lines of code to write *ONCE* and put in your utilities module
is a "magnum opus" and "a fair chunk of mucking about"?!  Oh my -- I
wonder what would count for you as parvus and incredibly tiny -- SIX
lines?  THREE?  ONE AND A HALF, for Pete's sake?!?!?!

If your problem with my code is simply that it uses parts of Python that
you're not familiar about, then I count this as a positive aspect of my
code, not a negative one: by providing motivation to study metaclasses
and inspect (by givin some small usefulness in very small space) it may
help you indirectly far more than directly.

> what? Early warning, a few microseconds ahead of the invocation of a
> method which will cause the stub in the base class to raise an
> exception?

Exactly.  Microseconds don't count, but stack levels do -- getting the
traceback end as close as possible to the real CAUSE of the problem,
rather than a few levels further down where the SYMPTOM appears, can
easily shave whole minutes off debugging time.  Since the whole of what
you call "magnum opus" took about 4 minutes to write, if it acts this
way twice I'm gaining.

Indeed, this issue is important enough that it might be worth one's
while to ensure the exception comes at class definition rather than
instantiation time -- e.g. by saying that a class must explicitly expose
(not just inherit) a class attribute '__abstract__' that's True, or else
having abstract methods still present is an error.  This obviously takes
a trivial mod to the (ha!) "magnum" opus, and makes errors even easier
to diagnose.  Still, it wasn't among the OP's desiderata, so I didn't
change the semantics in this way.


Note that either or both changes work particularly well wrt UNIT tests,
tests of some component which sees the abstract base class as 'external'
and thus not subject to its unit tests.  Say that 'external' component X
exposes ABC, the abstract base class, and many functions f, g, h, ...,
which take an ABC instance and do things with it.  My own component Y
subclasses ABC with WCC, the wannabe concrete class, and passes an
instance of WCC to *SOME* of X.f, X.g, X.h -- SOME, not necessarily ALL,
because UNIT tests don't have to fully probe interfaces BETWEEN
components!!!  (that's why they're UNIT tests, not INTEGRATION ones;-).

With Python's standard approach, no guarantee that WCC implements all
the methods it should.  Maybe it did implement all methods needed at the
time it was written, then X release 1.1 added a couple abstract methods
to ABC and a couple new functions j and k using them, and Y knows
nothing about this upgrade.  Y's unit tests are still gonna pass.  And
somebody ELSE who's instantiating a Y.WCC and passing the instance to
X.k is gonna feel the pain -- not in their unit tests, mind you, this
has VERY MUCH become a problem of inter-component orchestration.

With the cost of 12 lines, ONCE, in a utility module, you ensure halfway
decent unit tests WILL expose all 'failed to implement needed methods'
errors, even as X's specs keep evolving.  If you make any substantial
use of abstract classes and methods, the tradeoff is VERY favourable.


So, do _I_ use this?  Nah: I think abstract classes with
explicitly-abstract "somebody's gotta implement this!" methods are
rarely a good idea and tend to lead to fat base classes and overuse of
inheritance.  But if one disagrees, then I think that Python's suppport
for them with NotImplementedError is suboptimal, and some variation and
evolution along the lines of the tiny sketch I gave would be better.


Alex



More information about the Python-list mailing list