can i implement virtual functions in python ?

logistix at cathoderaymission.net logistix at cathoderaymission.net
Wed Oct 1 16:06:50 EDT 2003


"Andrew Dalke" <adalke at mindspring.com> wrote in message news:<jtseb.10860$NX3.5638 at newsread3.news.pas.earthlink.net>...
> logistix at cathoderaymission.net:
> > if you want to create a genuine Abstract Base Class, raise
> > NotImplementedErrors for the virual methods.  People will tell you
> > that this is not 'pythonic' (you should be using hasattr() to test for
> > interfaces) but I still find it useful from time to time.
> 
> Really?  I find hasattr to be non-Pythonic.  Just get the object, like
> 
>   try:
>     method = obj.function_name
>   except AttributeError:
>     ... not implemented ...
> 
> However, I do use NotImplementedError so the exception
> which percolates up is more obvious than AttributeError.  It also
> allows me to put in a docstring describing the interface requirements
> of derived classes.
> 
> I also don't like the double attribute lookup in
> 
>   if not hasattr(obj, "function_name"):
>     ... not implemented ...
>   else:
>     obj.function_name(...)
> 
> but that's more a personal issue than Pythonic vs. non-Pythonic.
> 

Yes,  try...except is equally valid, but I'm still brainwashed to
believe that exceptions are bad and should be avoided if possible.  I
still cringe when I write code that throws a 'StopIteration'
exception.  Like you say, its a personal issue, and I'll bring it up
with my therapist.

The point I was trying to make is that the least pythonic way to test
is use inheritance based interfaces and issubclass() or isinstance(). 
I've got yelled at every time I've posted code here that does it.

Still, once you get beyond trivial examples and you're writing special
purpose code I find it handy.  For example, what's the best way to
test for an interface in this code?

def foo(x):
    x.a()
    x.b()
    x.c()

Either using hasattr or or a try...except clause gets a little clunky.
 I'd just rather do something like:

class abstract:
    def a(self): raise NotImplementedError("Virtual Method")
    def b(self): raise NotImplementedError("Virtual Method")
    def c(self): raise NotImplementedError("Virtual Method")

class implementation(abstract):
    def a(self): print "a"
    def b(self): print "b"
    def c(self): print "c"

def foo(x):
    assert isinstance(x, abstract), "foo expects an 'abstract'
interface"
    x.a()
    x.b()
    x.c()

Or I suppose I could just let the interpreter throw an exception for
me when it can't find any of the appropriate methods. ;)




More information about the Python-list mailing list