Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Signature-based Function Overloading in Python

12 views
Skip to first unread message

Michael Rudolf

unread,
Feb 23, 2010, 1:25:24 PM2/23/10
to
Just a quick question about what would be the most pythonic approach in
this.

In Java, Method Overloading is my best friend, but this won't work in
Python:

>>> def a():
pass
>>> def a(x):
pass
>>> a()
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
a()
TypeError: a() takes exactly 1 argument (0 given)

So - What would be the most pythonic way to emulate this?
Is there any better Idom than:

>>> def a(x=None):
if x is None:
pass
else:
pass

?

Thanks,
Michael

Daniel Fetchinson

unread,
Feb 23, 2010, 1:49:53 PM2/23/10
to Python
> In Java, Method Overloading is my best friend, but this won't work in
> Python:
>
> >>> def a():
> pass
> >>> def a(x):
> pass
> >>> a()
> Traceback (most recent call last):
> File "<pyshell#12>", line 1, in <module>
> a()
> TypeError: a() takes exactly 1 argument (0 given)
>
> So - What would be the most pythonic way to emulate this?
> Is there any better Idom than:
>
> >>> def a(x=None):
> if x is None:
> pass
> else:
> pass

This is generally considered to be the pythonic idiom for what you describe.

Cheers,
Daniel


--
Psss, psss, put it down! - http://www.cafepress.com/putitdown

John Posner

unread,
Feb 23, 2010, 1:58:59 PM2/23/10
to spamf...@ch3ka.de

Consider this:

#------------------
def myfunc(*arglist):
if not arglist:
print "no arguments"
return
for i, arg in enumerate(arglist):
print "Argument %d is a %s, with value:" % (i, type(arg)),
print arg


myfunc()
print "---"
myfunc(1)
print "---"
myfunc(2, "three", [4, 5,6])
#------------------

program output:

no arguments
---
Argument 0 is a <type 'int'>, with value: 1
---
Argument 0 is a <type 'int'>, with value: 2
Argument 1 is a <type 'str'>, with value: three
Argument 2 is a <type 'list'>, with value: [4, 5, 6]


HTH,
John

Arnaud Delobelle

unread,
Feb 23, 2010, 3:35:04 PM2/23/10
to
Michael Rudolf <spamf...@ch3ka.de> writes:

There are a number of frameworks for function overloading out there. FWIW,
there is actually one in the Python sandbox (for Python 3):

http://svn.python.org/view/sandbox/trunk/Overload3K/

--
Arnaud

Lie Ryan

unread,
Feb 23, 2010, 5:55:21 PM2/23/10
to
On 02/24/10 05:25, Michael Rudolf wrote:
> Just a quick question about what would be the most pythonic approach in
> this.
>
> In Java, Method Overloading is my best friend, but this won't work in
> Python:
<snip>

> So - What would be the most pythonic way to emulate this?
> Is there any better Idom than:
>
>>>> def a(x=None):
> if x is None:
> pass
> else:
> pass

Python's idiom for this has always been to use "if arg is None:"; but
now with the (relatively) new decorator feature, though is not yet a
popular idiom, it is now possible to do something like this:

#!/usr/bin/env python

from functools import wraps

def overloaded(func):
@wraps(func)
def overloaded_func(*args, **kwargs):
for f in overloaded_func.overloads:
try:
return f(*args, **kwargs)
except TypeError:
pass
else:
# it will be nice if the error message prints a list of
# possible signatures here
raise TypeError("No compatible signatures")

def overload_with(func):
overloaded_func.overloads.append(func)
return overloaded_func

overloaded_func.overloads = [func]
overloaded_func.overload_with = overload_with
return overloaded_func

#############

@overloaded
def a():
print 'a() without args'
pass

@a.overload_with
def _(n):
# note that, just like property(), the function's name in
# the "def _(n):" line can be arbitrary, the important
# name is in the "@overloads(a)" line
print 'a() with args'
pass

a()
a(4)
a(4, 5) # ERROR: no matching signature

PS: I posted the code to recipe book, for future reference:
http://code.activestate.com/recipes/577064-simple-function-overloading-with-decorator/

Jean-Michel Pichavant

unread,
Feb 24, 2010, 5:28:13 AM2/24/10
to Michael Rudolf, pytho...@python.org
This is the way to do it python, and it has its advantages: 1 docstring,
1 way do do it, 1 interface.

JM

Michael Rudolf

unread,
Feb 24, 2010, 6:42:08 AM2/24/10
to
First: Thanks for all the replies so far, they really helped me.

Am 24.02.2010 11:28, schrieb Jean-Michel Pichavant:
>> >>> def a(x=None):
>> if x is None:
>> pass
>> else:
>> pass
>>

> This is the way to do it python, and it has its advantages: 1 docstring,
> 1 way do do it, 1 interface.

Yes, I see. Actually I do now realize that even in Java I use method
overloading mostly to implement optional arguments anyway, like:

void constructor(){this.foo='foo'; this.initotherstuff();}
void constructor(int x) {this.x=x; this.constructor();}

and so on.

So most of the time the idiom above is exactly what I need, as the
versions of the function share code anyway.

But there are also cases where they do something completely different -
in these cases I might use one of the other solutions provided here or
simply make two or three functions and name them appropiately.

I do now see that the pythonic approach is the "best" for most cases,
but I really loved to see that you *can* do overloading in a convenient
way if you really want to :D Those decorators just rock :D

Thanks again,
Michael

Diez B. Roggisch

unread,
Feb 24, 2010, 6:05:35 PM2/24/10
to
Am 24.02.10 12:42, schrieb Michael Rudolf:

You can do, see packages such as PEAK rules. They offer not only
type-based overloading, but also value-based.

Diez

Jean-Michel Pichavant

unread,
Feb 25, 2010, 5:32:30 AM2/25/10
to Michael Rudolf, pytho...@python.org
You said it yourself: "simply make two or three functions and name them
appropiately" :-)

When 2 methods of a class were to have the same name for doing
completely different things like you said, there's a design flaw to my
opinion.

JM

Jean-Michel Pichavant

unread,
Feb 25, 2010, 5:58:30 AM2/25/10
to Jean-Michel Pichavant, pytho...@python.org, Michael Rudolf
Jean-Michel Pichavant wrote:
> You said it yourself: "simply make two or three functions and name
> them appropiately" :-)
>
> When 2 methods of a class were to have the same name for doing
> completely different things like you said, there's a design flaw to my
> opinion.
>
> JM
I wonder if I've just written that my opinion is flawed... It surely is,
but that's not why I meant :-)

JM

Michael Rudolf

unread,
Feb 25, 2010, 8:44:20 AM2/25/10
to
Am 25.02.2010 11:58, schrieb Jean-Michel Pichavant:
>> You said it yourself: "simply make two or three functions and name
>> them appropiately" :-)
>>
>> When 2 methods of a class were to have the same name for doing
>> completely different things like you said, there's a design flaw to my
>> opinion.
>>
>> JM
> I wonder if I've just written that my opinion is flawed... It surely is,
> but that's not why I meant :-)

:D

Well, there might be cases when someone wants to do this. consider:
(pseudocode - this is *not* python ;)

class Machines (Object):
@classmethod
def shutdown(cls, Machine, emergency=False):
try:
if Machine is instanceof(Fileservers):
if not emergency:
Machine.unmount_raid_first()
...
Machine.halt()
if Machine is instanceof(Router):
if not emergency:
cls.shutdown(Machine.attachedmachines)
...
...
finally:
if emergency and Machine has powerswitch:
Machine.powerswitch.Off()
@classmethod
def emergency(cls):
for machine in cls.instances:
cls.shutdown(machine, 1)

Other design patterns might me good too, but I like the idea of having
emergency protocols in *one* place here. But without method overloading,
there are many many nested 'if's.

One could say that the machines have to know how to shut down itself,
but there might be dependencies they do not know about, and as said, it
clutters the emergency protocol all over the modules.

One could define normal_shutdown() and emergency_shutdown(), but I do
not like this eighter, and there are still many 'if's to seperate the types.

There are cases where *no* solution is perfect, and those are the cases
where "2 methods of a class were to have the same name for doing
completely different things" or other messy things like this are IMO
*NOT* a design flaw.

Regards,
Michael

Bruno Desthuilliers

unread,
Feb 25, 2010, 11:16:58 AM2/25/10
to
Michael Rudolf a �crit :
(snip)

> (pseudocode - this is *not* python ;)
>
> class Machines (Object):
> @classmethod
> def shutdown(cls, Machine, emergency=False):
> try:
> if Machine is instanceof(Fileservers):


> if not emergency:
> Machine.unmount_raid_first()
> ...
> Machine.halt()
> if Machine is instanceof(Router):
> if not emergency:
> cls.shutdown(Machine.attachedmachines)
> ...
> ...
> finally:
> if emergency and Machine has powerswitch:
> Machine.powerswitch.Off()
> @classmethod
> def emergency(cls):
> for machine in cls.instances:
> cls.shutdown(machine, 1)
>

> One could say that the machines have to know how to shut down itself,

Indeed !-)

> but there might be dependencies they do not know about,

Then it's the "Machines" (or a "MachineShutdownProtocol" or whatever)
responsability to manage correct operation order, and you need an API to
allow communication between the Machine objects and the WhateverItsName
object in charge of monitoring the process.

All this if you do care about correct OO design, of course - as far as
I'm concerned, practicallity beats purity !-)

> and as said, it
> clutters the emergency protocol all over the modules.

Tradeoff, tradeoff. The above won't work for a "plug&play" system.

> There are cases where *no* solution is perfect,

There is always at least one "less worse" solution, depending on the
concrete use case.

alex23

unread,
Feb 27, 2010, 4:00:00 AM2/27/10
to
Michael Rudolf <spamfres...@ch3ka.de> wrote:
> In Java, Method Overloading is my best friend

Guido wrote a nice article[1] on "multimethods" using decorators,
which Ian Bicking followed up on[2] with a non-global approach.

1: http://www.artima.com/weblogs/viewpost.jsp?thread=101605
2: http://blog.ianbicking.org/more-on-multimethods.html

Michael Rudolf

unread,
Feb 28, 2010, 1:07:41 AM2/28/10
to
0 new messages