Method overloading?

Paul McGuire ptmcg at austin.rr.com
Thu Feb 15 00:58:35 EST 2007


On Feb 14, 10:54 pm, "placid" <Bul... at gmail.com> wrote:
> Hi all,
>
> Is it possible to be able to do the following in Python?
>
> class Test:
>     def __init__(self):
>         pass
>
>     def puts(self, str):
>         print str
>
>     def puts(self, str,str2):
>         print str,str2
>
> if __name__ == "__main__":
>     t = Test()
>     t.puts("hi")
>     t.puts("hi","hello")
>
> Cheers

No, Python does not do overloading as part of the language, you have
to do the variable argument interpretation for yourself.

For instance, if you want a method to accept a single argument of
various types, it would look something like this:

def multiAccept( argOfVariousTypes ):
    if isinstance(argOfVariousTypes,int):
        # treat like an int
    elif isinstance(argOfVariousTypes,float):
        # treat like a float
    elif isinstance(argOfVariousTypes,(list,tuple)):
        # treat like a container

This is not really all that Pythonic a style.  More generally accepted
is to just *use* the arg in the way you want, and throw exceptions
when the arg doesn't conform - if the user sends invalid args, let him/
her deal with the resulting exceptions.

Here's a method that will handle an arg of various types:

def containerStats(cont):
    print "Container is of type %s" % cont.__class__.__name__
    print "- min value is", min(cont)
    print "- max value is", max(cont)
    print "- length is", len(cont)

>>> containerStats( [1,2,3] )
Container is of type list
- min value is 1
- max value is 3
- length is 3
>>> containerStats( ('abc', 'def', 123) )
Container is of type tuple
- min value is 123
- max value is def
- length is 3
>>> containerStats( dict(zip("abc",range(3))) )
Container is of type dict
- min value is a
- max value is c
- length is 3
>>> containerStats("lsjlsja;s")
Container is of type str
- min value is ;
- max value is s
- length is 9

What's really interesting, is that this method could have been written
back in Python 1.5 days, and in Python 2.3 with the introduction of
sets, we could use this new data type, which didn't even exist when
the original code was written, and get some interesting results:

>>> containerStats(set("SLKFJDSLJDFSLJFSLKFS"))
Container is of type set
- min value is D
- max value is S
- length is 6


And if we don't send a container?  This happens:

>>> containerStats( 3.14159 )
Container is of type float
- min value is
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 3, in containerStats
TypeError: iteration over non-sequence

But what did I expect, sending a single float to a method that clearly
expects a sequence of some kind?!

Python does include in the language the ability to send a variable
number of arguments to a method, using *args and **kwargs.  Your
original puts method can accept a variable argument list in something
like this:

class Test:
    def __init__(self):
        pass

    def puts(self, *args):
        print " ".join(map(str,args))

if __name__ == "__main__":
    t = Test()
    t.puts("hi")
    t.puts("hi","hello")
    t.puts("hi",1,3.45)

Prints:
hi
hi hello
hi 1 3.45

Combine these techniques, and you can overload your methods to your
heart's content!

-- Paul





More information about the Python-list mailing list