Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use method overloading in Python?

People also ask

Can we do method overloading in Python?

Like other languages (for example, method overloading in C++) do, python does not support method overloading by default.

How do you use method overloading?

In Java, two or more methods may have the same name if they differ in parameters (different number of parameters, different types of parameters, or both). These methods are called overloaded methods and this feature is called method overloading. For example: void func() { ... }


It's method overloading, not method overriding. And in Python, you do it all in one function:

class A:

    def stackoverflow(self, i='some_default_value'):
        print 'only method'

ob=A()
ob.stackoverflow(2)
ob.stackoverflow()

You can't have two methods with the same name in Python -- and you don't need to.

See the Default Argument Values section of the Python tutorial. See "Least Astonishment" and the Mutable Default Argument for a common mistake to avoid.

See PEP 443 for information about the new single dispatch generic functions in Python 3.4.


You can also use pythonlangutil:

from pythonlangutil.overload import Overload, signature

class A:
    @Overload
    @signature()
    def stackoverflow(self):    
        print 'first method'

    @stackoverflow.overload
    @signature("int")
    def stackoverflow(self, i):
        print 'second method', i

In Python, you don't do things that way. When people do that in languages like Java, they generally want a default value (if they don't, they generally want a method with a different name). So, in Python, you can have default values.

class A(object):  # Remember the ``object`` bit when working in Python 2.x

    def stackoverflow(self, i=None):
        if i is None:
            print 'first form'
        else:
            print 'second form'

As you can see, you can use this to trigger separate behaviour rather than merely having a default value.

>>> ob = A()
>>> ob.stackoverflow()
first form
>>> ob.stackoverflow(2)
second form

While agf was right with the answer in the past, now with PEP-3124 we got our syntactic sugar.

See typing documentation for details on the @overload decorator, but note that this is really just syntactic sugar and IMHO this is all people have been arguing about ever since.

Personally, I agree that having multiple functions with different signatures makes it more readable then having a single function with 20+ arguments all set to a default value (None most of the time) and then having to fiddle around using endless if, elif, else chains to find out what the caller actually wants our function to do with the provided set of arguments. This was long overdue following the Python Zen:

Beautiful is better than ugly.

and arguably also

Simple is better than complex.

Straight from the official Python documentation linked above:

from typing import overload
@overload
def process(response: None) -> None:
    ...
@overload
def process(response: int) -> Tuple[int, str]:
    ...
@overload
def process(response: bytes) -> str:
    ...
def process(response):
    <actual implementation>

EDIT: for anyone wondering why this example is not working as you'd expect if from other languages I'd suggest to take a look at this discussion. The @overloaded functions are not supposed to have any actual implementation. This is not obvious from the example in the Python documentation.


You can't, never need to and don't really want to.

In Python, everything is an object. Classes are things, so they are objects. So are methods.

There is an object called A which is a class. It has an attribute called stackoverflow. It can only have one such attribute.

When you write def stackoverflow(...): ..., what happens is that you create an object which is the method, and assign it to the stackoverflow attribute of A. If you write two definitions, the second one replaces the first, the same way that assignment always behaves.

You furthermore do not want to write code that does the wilder of the sorts of things that overloading is sometimes used for. That's not how the language works.

Instead of trying to define a separate function for each type of thing you could be given (which makes little sense since you don't specify types for function parameters anyway), stop worrying about what things are and start thinking about what they can do.

You not only can't write a separate one to handle a tuple vs. a list, but also don't want or need to.

All you do is take advantage of the fact that they are both, for example, iterable (i.e. you can write for element in container:). (The fact that they aren't directly related by inheritance is irrelevant.)