Zero Days
Zero Days

Reputation: 859

type function overloading in python

Python doesn't do overloading like Java or C, because Python is a dynamically typed language. And we can just use *args instead.

Java style:

class DisplayOverloading
    {
        public void disp(char c)
        {
             System.out.println(c);
        }
        public void disp(char c, int num)  
        {
             System.out.println(c + " "+num);
        }
    }

but python call second Print method when call it:

class Dog:
    def __init__(self,age,name):
        self.age=age
        self.name=name

    def Print(self,age):
        print(self.age)

    def Print(self,name,age):
        print(self.name)

d=Dog(5,'dobi') 
d.Print('dobi',5)#dobi
d.Print(5)       #Error !

actually second Print replace to first Print.

But there is something strange here about the type function, it does different things when passed in a different number of arguments:

Return the object type:

>>> x=12
>>> y=str()
>>> 
>>> type(x)
<class 'int'>
>>> type(y)
<class 'str'>

or make a class:

>>> klass=type('MyClass',(),{})
>>> klass
<class '__main__.MyClass'>

Is this overloading? If so, why can't we use overloading in other methods?

Upvotes: 1

Views: 1028

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1122152

type() isn't using overloading. It is using the C-code equivalent of *args to alter behaviour based on how many arguments you passed in. If you are interested in the specifics, see the type_new function:

/* Special case: type(x) should return x->ob_type */
{
    const Py_ssize_t nargs = PyTuple_GET_SIZE(args);
    const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds);

    if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) {
        PyObject *x = PyTuple_GET_ITEM(args, 0);
        Py_INCREF(Py_TYPE(x));
        return (PyObject *) Py_TYPE(x);
    }

which essentially tests if len(args) == 1 and not kwargs, as well as making sure the first argument is the type object itself and not a subclass.

You could do something similar with your Dog.Print() method; if args is not empty assume it was called with name, age instead of just age:

def Print(self, age, *args):
    if args:
        name, age = args + (age,)
    else:
        name = None
    if name is not None:
        print(name)
    print(age)

although that would make it a terribly bad API. It is better to add optional arguments to the end:

def Print(self, age, name=None):
    if name is not None:
        print(name)
    print(age)

as that reduces confusion and is easier to remember.

Upvotes: 2

DorElias
DorElias

Reputation: 2313

It can be done by doing

def func(*args):
    if len(args) == 2:
        #do something 
    else:
        #do something else with args

Upvotes: 0

Related Questions