#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2002
    Location
    Minnesota
    Posts
    0
    Rep Power
    0

    polymorphic function selection


    want to be able to create some functions that take objects as arguments, and
    decide which function is invoked based on the type of the object passed, much
    like you'd do in c++..

    But, since functions do not declare the types for parameters in python, how
    can this be done?

    sample c++ syntax that I'd like to be able to handle:


    void foo(int a)
    {
    }

    void foo(SomeClass& s)
    {
    }

    void foo(SomeOtherClass& o)
    {
    }

    now, I'd like to use these functions like this:

    int a;
    SomeClass s;
    SomeOtherClass o;

    foo(a);
    foo(s);
    foo(o):

    can this be done in python? If not, it seems like a horrible oversight.
  2. #2
  3. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2002
    Posts
    32
    Rep Power
    13
    nope you can't do that in Python... you can, however, do what you want with some simple logic using the type() function to determine the type of the arguments and then deciding what exactly to do...

    it's not a horrible oversight i think... i can't explain why but i believe it has to do with Python's dynamic typing feature... a guru could explain better
  4. #3
  5. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2002
    Location
    Minnesota
    Posts
    0
    Rep Power
    0
    Thanks for your reply. I did some reading, and I agree with your assessment. It's just cumbersome to replace the above code with an if-elif-else. It would be better with a switch statement, but of course, Python doesn't have that either...

    Besides those 2 failings, it's a pretty cool language!
  6. #4
  7. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2002
    Posts
    32
    Rep Power
    13
    not having a switch statement isn't a failing... Python's syntax is so clean that you can write a simple if-elif-else statement in place of a switch and still have legible code...

    anyway, yes your right Python's a pretty neat language and i'm really 'into' it right now
  8. #5
  9. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2002
    Posts
    0
    Rep Power
    0
    Hi.

    You may address your question to Python lists and I think it'll help you.

    Overloading is a technique depricated by a lot of theoretitions and I think it's a god idea not to support overloading directly.

    Nonetheless, one can easily implement such functionality. I don't think that 'swict' of 'if-elif-else' is a good way to do it, but dictionaries could be of great help. Let's consider an example:

    class A: pass
    class B: pass

    def overloaded(obj)
    def fooA(obj): return "In fooA"
    def fooB(obj): return "In fooB"

    dispatcher = {A: fooA, B: fooB}
    return (dispatcher[obj.__class__])(obj)

    Then
    print overloaded(A())

    should print "In fooA"

    print overlaoded(B())

    should print "In fooB"

    Hope it helps,
    Anton.
  10. #6
  11. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2002
    Posts
    32
    Rep Power
    13
    excellent idea Anton!
  12. #7
  13. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2002
    Posts
    1
    Rep Power
    0

    polymorphic function selection


    Dispatch tables are very handy things when your keys are strings or other literals, but not such a good idea for classes. This is mainly because you lose all potential for catching inherited classes. The proper solution requires isinstance, which in turn requires an if-else ladder, though putting this in the called function isn't as ugly as described. An untested example:
    Code:
    class A: pass
    class B: pass
    class C(A): pass
    
    def foo(obj):
        if isinstance(obj, A):
            return fooA(obj)
        elif isinstance(obj, B):
            return fooB(obj)
        else:
            raise TypeError
    
    def fooA(obj): return "In fooA"
    def fooB(obj): return "In fooB"
    print foo(A())

    should print "In fooA"

    print foo(B())

    should print "In fooB"

    print foo(C())

    should print "In fooA"


    If you are really set on a dispatch table, you could modify the above with:

    Code:
    dispatch_table = {
        A: fooA,
        B: fooB,
    }
    
    def foo(obj):
        for x in dispatch_table.keys():
            if isinstance(obj, x):
                return dispatch_table[x](obj)
        raise TypeError
    You should get the same results.

    This is especially important since you don't know who will subclass the expected classes in the future and call your functions. You will really lose polymorphic potential here.
  14. #8
  15. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2002
    Posts
    0
    Rep Power
    0
    Hi all,

    Thanks to OB_redemption for kind words.

    And special thanks to moramis --- I really forgot about inheritance.

    Just a little note: if one want to support inheritance, lists or tuples could be better solution. Lists are better, if you want to override functionaltiy for base class, for lookup order for dictionaries is undefined (at least one shouldn't rely on it) and with lists one can simple added handlers at the beginning
    Anyway general overloading could be not so easy to implement.

    And the last: in a lot of cases overloading can be implemented with class methods:

    class A:
    def doIt(): print "In A"
    class B:
    def doIt(): print "In B"

    def foo(obj): obj.doIt() # maybe add a test for presence of the method

IMN logo majestic logo threadwatch logo seochat tools logo