John Machin <[EMAIL PROTECTED]> 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 -- http://mail.python.org/mailman/listinfo/python-list