Polymorphism with callables in Python
Question: I have an interface class called iResource, and a number of subclasses, each
of which implement the "request" method. The request functions use socket I/O
to other machines, so it makes sense to run them asynchronously, so those
other machines can work in parallel.

The problem is that when I start a thread with iResource.request and give it a
subclass as the first argument, it'll call the superclass method. If I try to
start it with "type(a).request" and "a" as the first argument, I get "" for
the value of type(a). Any ideas what that means and how to get the true type
of the method? Can I formally declare an abstract method in Python somehow?

EDIT: Including code.

    
    
    def getSocialResults(self, query=''):
        #for a in self.types["social"]: print type(a)
        tasks = [type(a).request for a in self.types["social"]]
        argss = [(a, query, 0) for a in self.types["social"]]
    
        grabbers = executeChainResults(tasks, argss)
    
        return igrabber.cycleGrabber(grabbers)
    

"executeChainResults" takes a list "tasks" of callables and a list "argss" of
args-tuples, and assumes each returns a list. It then executes each in a
separate thread, and concatenates the lists of results. I can post that code
if necessary, but I haven't had any problems with it so I'll leave it out for
now.

The objects "a" are DEFINITELY not of type iResource, since it has a single
constructor that just throws an exception. However, replacing
"type(a).request" with "iResource.request" invokes the base class method.
Furthermore, calling "self.types["social"][0].request" directly works fine,
but the above code gives me: "type object 'instance' has no attribute
'request'".

Uncommenting the commented line prints `<type 'instance'>` several times.


Answer: You can just use the bound method object itself:

    
    
    tasks = [a.request for a in self.types["social"]]
    #        ^^^^^^^^^
    grabbers = executeChainResults(tasks, [(query, 0)] * len(tasks))
    #                                     ^^^^^^^^^^^^^^^^^^^^^^^^^
    

If you insist on calling your methods through the base class you could also do
it like this:

    
    
    from abc import ABCMeta
    from functools import wraps
    
    def virtualmethod(method):
        method.__isabstractmethod__ = True
        @wraps(method)
        def wrapper(self, *args, **kwargs):
            return getattr(self, method.__name__)(*args, **kwargs)
        return wrapper
    
    class IBase(object):
        __metaclass__ = ABCMeta
        @virtualmethod
        def my_method(self, x, y):
            pass
    
    class AddImpl(IBase):
        def my_method(self, x, y):
            return x + y
    
    class MulImpl(IBase):
        def my_method(self, x, y):
            return x * y
    
    items = [AddImpl(), MulImpl()]
    
    for each in items:
        print IBase.my_method(each, 3, 4)
    
    b = IBase()  #  <-- crash
    

Result:

    
    
    7
    12
    Traceback (most recent call last):
      File "testvirtual.py", line 30, in <module>
        b = IBase()
    TypeError: Can't instantiate abstract class IBase with abstract methods my_method
    

Python doesn't support interfaces as e.g. Java does. But with the `abc` module
you can ensure that certain methods must be implemented in subclasses.
Normally you would do this with the `abc.abstractmethod()` decorator, but you
still could not call the subclasses method through the base class, like you
intend. I had a similar question once and I had the idea of the
`virtualmethod()` decorator. It's quite simple. It essentially does the same
thing as `abc.abstratmethod()`, but also redirects the call to the subclasses
method. The specifics of the `abc` module can be found in [the
docs](http://docs.python.org/library/abc.html) and in
[PEP3119](http://www.python.org/dev/peps/pep-3119/).

BTW: I assume you're using Python >= 2.6.

