Method overloading?

Discussion in 'Python' started by placid, Feb 15, 2007.

  1. placid

    placid Guest

    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
     
    placid, Feb 15, 2007
    #1
    1. Advertising

  2. On 2007-02-15, placid <> wrote:

    > 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")


    You tell us: what happened when you tried it?

    And then what happens when you do this?

    class Test:
    def __init__(self):
    pass

    def puts(self, *args):
    print ' '.join(args)

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

    Now an exercise for the gentle reader: change the puts method
    so that this call works:

    t.puts("hi",1,3.45)

    --
    Grant Edwards grante Yow! Yow! I'm imagining
    at a surfer van filled with
    visi.com soy sauce!
     
    Grant Edwards, Feb 15, 2007
    #2
    1. Advertising

  3. placid

    placid Guest

    On Feb 15, 4:04 pm, Grant Edwards <> wrote:
    > On 2007-02-15, placid <> wrote:
    >
    >
    >
    > > 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")

    >
    > You tell us: what happened when you tried it?


    Well, when i run it i get this error "puts() takes exactly 3 arguments
    (2 given)" which means that the second a time i try to define the
    puts() method "overwrites" the first one

    >
    > And then what happens when you do this?
    >
    > class Test:
    > def __init__(self):
    > pass
    >
    > def puts(self, *args):
    > print ' '.join(args)
    >
    > if __name__ == "__main__":
    > t = Test()
    > t.puts("hi")
    > t.puts("hi","hello")


    but this isn't overloading.

    >
    > Now an exercise for the gentle reader: change the puts method
    > so that this call works:
    >
    > t.puts("hi",1,3.45)
    >
    > --
    > Grant Edwards grante Yow! Yow! I'm imagining
    > at a surfer van filled with
    > visi.com soy sauce!
     
    placid, Feb 15, 2007
    #3
  4. placid

    Paul McGuire Guest

    On Feb 14, 10:54 pm, "placid" <> 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
     
    Paul McGuire, Feb 15, 2007
    #4
  5. On Wed, 14 Feb 2007 21:12:39 -0800, placid wrote:

    > On Feb 15, 4:04 pm, Grant Edwards <> wrote:
    >> On 2007-02-15, placid <> wrote:
    >>
    >>
    >>
    >> > 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")

    >>
    >> You tell us: what happened when you tried it?

    >
    > Well, when i run it i get this error "puts() takes exactly 3 arguments
    > (2 given)" which means that the second a time i try to define the
    > puts() method "overwrites" the first one


    Yes, that's right. It is no different from doing this:

    x = 1
    x = 2


    >> And then what happens when you do this?
    >>
    >> class Test:
    >> def __init__(self):
    >> pass
    >>
    >> def puts(self, *args):
    >> print ' '.join(args)
    >>
    >> if __name__ == "__main__":
    >> t = Test()
    >> t.puts("hi")
    >> t.puts("hi","hello")

    >
    > but this isn't overloading.


    Neither was your first example.


    This is an example of overloading:

    class Cheese(object):
    def flavour(self):
    return "tasty and scrumptious"
    def colour(self):
    return "yellow"


    Now we define a sub-class which overloads some methods:

    class BlueVein(Cheese):
    def colour(self):
    return "white with blue veins"

    Testing it:


    >>> c = BlueVein()
    >>> c.flavour() # inherited from the super class

    'tasty and scrumptious'
    >>> c.colour() # over-ridden by the sub-class

    'white with blue veins'
    >>> super(BlueVein, c).colour() # call the super class method

    'yellow'


    I hope this helps.



    --
    Steven D'Aprano
     
    Steven D'Aprano, Feb 15, 2007
    #5
  6. On Wed, 14 Feb 2007 21:58:35 -0800, Paul McGuire wrote:

    > 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


    Is that really called "overloading"? I've never (knowingly) come across
    the term being used in that context before. I've always known that as
    "multiple dispatch" or "polymorphism", depending on whether you or the
    compiler handles the dispatching.

    Actually, I tell a lie. I've always know it as "a function that can handle
    different types of arguments" :)



    --
    Steven D'Aprano
     
    Steven D'Aprano, Feb 15, 2007
    #6
  7. placid

    Paul McGuire Guest

    On Feb 15, 12:23 am, Steven D'Aprano
    <> wrote:
    > On Wed, 14 Feb 2007 21:58:35 -0800, Paul McGuire wrote:
    > > 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

    >
    > Is that really called "overloading"? I've never (knowingly) come across
    > the term being used in that context before. I've always known that as
    > "multiple dispatch" or "polymorphism", depending on whether you or the
    > compiler handles the dispatching.
    >


    Well, I think "overloading" and "Python" may not even belong in the
    same sentence, actually. "Overloading" is used in C++, Java and C# to
    describe a single method name with multiple signatures. It is not
    really possible to implement such a thing in Python, which just binds
    methods to names, and duplicate definitions of methodX just replace
    the former with the latter.

    But from the standpoint of the caller, calls to methodX() with various
    numbers and types of arguments looks just the same as it does in Java
    or C# with method overloading, and could reasonably be thought of as
    such - what does the caller care how methodX handles these various
    calls, whether with 1 hyper-adaptive method implementation or a dozen
    type-specific ones?

    I've had this discussion before, but I personally tend to reserve the
    term "polymorphism" for instance-level behavior, such as when a
    collection of instances that all derive from a common base class have
    overridden method definitions. The typical example is a list of
    Shapes, each implementing its own draw() method, so that they
    polymorphically do their subclass-appropriate draw behavior. Or for a
    Strategy pattern implementation (one of my favorite), where derived
    strategy classes implement a base interface with their separate
    behaviors, and each is accessed through the interface definition.

    The beauty of Python's duck-typing is that this same kind of
    polymorphism can be achieved without the burden of class inheritance
    hierarchies. As long as the instances referenced all implement
    methodX(), Python is happy. If I'm desperate, I could even
    dynamically attach a do-nothing or default version of such a method if
    it were not already defined for an instance. Try *that* in C++
    (without a horrifying haystack of angle brackets)!

    I have heard "overloading" referred to as "method polymorphism", but I
    think this is just a dilution of the "polymorphism" term, with no
    additional knowledge transfer gained.

    -- Paul
     
    Paul McGuire, Feb 15, 2007
    #7
  8. placid

    Troy Melhase Guest

    On 14 Feb 2007 20:54:31 -0800, placid <> wrote:
    > class Test:
    > def __init__(self):
    > pass
    >
    > def puts(self, str):
    > print str
    >
    > def puts(self, str,str2):
    > print str,str2


    you might look into the overloading module and its decorator. source
    is in the sandbox:

    http://svn.python.org/view/sandbox/trunk/overload/overloading.py

    using it, you could re-write your example as:

    #
    from overloading import overloaded

    class Test(object):

    @overloaded
    def puts(self, S):
    print S

    @puts.register(object, str, str)
    def puts_X(self, S, S2):
    print S, S2

    two things to note. first, i changed your class to derive from
    object. I don't know if that's required, but i suspect it is.

    second, i changed your argument names. the argument names in your
    example shadow built-in names. you shouldn't do that in any case, but
    it could become especially confusing using the overloaded decorator,
    which relies on argument type to select the correct method.
     
    Troy Melhase, Feb 15, 2007
    #8
  9. placid

    Guest

    On 15 fév, 09:32, "Troy Melhase" <> wrote:
    > On 14 Feb 2007 20:54:31 -0800, placid <> wrote:
    >
    > > class Test:
    > > def __init__(self):
    > > pass

    >
    > > def puts(self, str):
    > > print str

    >
    > > def puts(self, str,str2):
    > > print str,str2

    >
    > you might look into the overloading module and its decorator. source
    > is in the sandbox:
    >
    > http://svn.python.org/view/sandbox/trunk/overload/overloading.py
    >

    Or have a look at Philip Eby's dispatch package, which is kind of
    overloading on steroids...
     
    , Feb 15, 2007
    #9
  10. On 2007-02-15, placid <> wrote:

    >> > 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")

    >>
    >> You tell us: what happened when you tried it?

    >
    > Well, when i run it i get this error "puts() takes exactly 3 arguments
    > (2 given)" which means that the second a time i try to define the
    > puts() method "overwrites" the first one


    Correct. That means it's not possible to do what you wrote.

    >> And then what happens when you do this?
    >>
    >> class Test:
    >> def __init__(self):
    >> pass
    >>
    >> def puts(self, *args):
    >> print ' '.join(args)
    >>
    >> if __name__ == "__main__":
    >> t = Test()
    >> t.puts("hi")
    >> t.puts("hi","hello")

    >
    > but this isn't overloading.


    No, it isn't. [You can't overload methods in Python. Was that
    your question?] It is, however, the way one does what you
    appear to be trying to do.

    --
    Grant Edwards grante Yow! If I am elected no
    at one will ever have to do
    visi.com their laundry again!
     
    Grant Edwards, Feb 15, 2007
    #10
  11. placid

    Neil Cerutti Guest

    On 2007-02-15, Steven D'Aprano <> wrote:
    >> 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

    >
    > Is that really called "overloading"? I've never (knowingly)
    > come across the term being used in that context before. I've
    > always known that as "multiple dispatch" or "polymorphism",
    > depending on whether you or the compiler handles the
    > dispatching.


    It's due to vague terminology that we're using.

    What the OP wanted to know about was static polymorphism of names
    based on function signatures, often refered to informally in the
    context of C++ as "function overloading", though it's really
    "identifier overloading where identifier refers to a function or
    member function".

    What Python provides is dynamic polymorphism of names with
    single-dispatch.

    I think. ;-)

    --
    Neil Cerutti
     
    Neil Cerutti, Feb 15, 2007
    #11
  12. placid

    placid Guest

    On Feb 16, 3:37 am, Neil Cerutti <> wrote:
    > On 2007-02-15, Steven D'Aprano <> wrote:
    >
    > >> 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

    >
    > > Is that really called "overloading"? I've never (knowingly)
    > > come across the term being used in that context before. I've
    > > always known that as "multiple dispatch" or "polymorphism",
    > > depending on whether you or the compiler handles the
    > > dispatching.

    >
    > It's due to vague terminology that we're using.
    >
    > What the OP wanted to know about was static polymorphism of names
    > based on function signatures, often refered to informally in the
    > context of C++ as "function overloading", though it's really
    > "identifier overloading where identifier refers to a function or
    > member function".


    This what i was asking.

    >
    > What Python provides is dynamic polymorphism of names with
    > single-dispatch.
    >
    > I think. ;-)
    >
    > --
    > Neil Cerutti


    Thank you all for the information.
     
    placid, Feb 15, 2007
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Iyer, Prasad C

    Overloading __init__ & Function overloading

    Iyer, Prasad C, Sep 30, 2005, in forum: Python
    Replies:
    3
    Views:
    6,451
    Fredrik Lundh
    Sep 30, 2005
  2. Fredrik Lundh
    Replies:
    0
    Views:
    478
    Fredrik Lundh
    Sep 30, 2005
  3. Steve Holden
    Replies:
    0
    Views:
    453
    Steve Holden
    Sep 30, 2005
  4. Iyer, Prasad C
    Replies:
    4
    Views:
    604
    John J. Lee
    Sep 30, 2005
  5. Fredrik Lundh
    Replies:
    0
    Views:
    421
    Fredrik Lundh
    Sep 30, 2005
Loading...

Share This Page