How about "pure virtual methods"?

Scott David Daniels Scott.Daniels at Acm.Org
Sun Dec 19 23:07:53 CET 2004


John Machin wrote (of Alex Martelli's sketch):
> Thank you for the motivation. I now understand what it is attempting to
> do. Unfortunately it doesn't succeed. Instead of:
> if v is notimplemented: abstract_methods.append(n)
> you need:
> if v.im_func is notimplemented: abstract_methods.append(n)

Here is an implementation from that sketch:

from inspect import getmembers

class MustImplement(type):
     '''A metaclass to detect instantiation of abstract classes'''

     def __init__(class_, name, bases, defined):
         super(MustImplement, class_).__init__(name, bases, defined)
         class_._abstract_methods = sorted(name
                                 for name, value in getmembers(class_)
                                 if value is NotImplemented)

     def __call__(class_, *args, **kwargs):
         if class_._abstract_methods:
             raise NotImplementedError, 'Abstract class %s needs %s.' % (
                    class_.__name__, ', '.join(class_._abstract_methods))
         return super(MustImplement, class_).__call__(*args, **kwargs)


class Abstract(object):
     '''A class to stick anywhere in an inheritance chain'''
     __metaclass__ = MustImplement


def notimplemented(method):
     '''A decorator for those who prefer the parameters declared.'''
     return NotImplemented


if __name__ == '__main__':
     class SomeBase(dict):
         __metaclass__ = MustImplement
         needed = also_needed = NotImplemented
     class Derived(SomeBase):
         def needed(x): return 3
     class Further(Derived):
         def also_needed(x): return 1

     class SomethingMissing(object):
         @notimplemented
         def function(): return 23

     class UsesMissing(SomethingMissing, Abstract): pass

     f = Further() # works
     try:
         d = Derived()
     except NotImplementedError, e:
         print 'Got expected exception:', e
     else:
         raise ValueError, 'Did not get expected exception'

     s = SomethingMissing() # works
     try:
         u = UsesMissing()
     except NotImplementedError, e:
         print 'Got expected exception:', e
     else:
         raise ValueError, 'Did not get expected exception'


--Scott David Daniels
Scott.Daniels at Acm.Org



More information about the Python-list mailing list