[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Signature-based Function Overloading in Python

Michael Rudolf

2/23/2010 6:25:00 PM

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
13 Answers

Daniel Fetchinson

2/23/2010 6:50:00 PM

0

> 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...

John Posner

2/23/2010 6:59:00 PM

0

On 2/23/2010 1:25 PM, 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:
>
> >>> 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
>

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

2/23/2010 8:35:00 PM

0

Michael Rudolf <spamfresser@ch3ka.de> writes:

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

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/O...

--
Arnaud

Lie Ryan

2/23/2010 10:55:00 PM

0

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-...

Jean-Michel Pichavant

2/24/2010 10:28:00 AM

0

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:
>
> >>> 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
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

2/24/2010 11:42:00 AM

0

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

2/24/2010 11:06:00 PM

0

Am 24.02.10 12:42, schrieb Michael Rudolf:
> 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

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

Diez

Jean-Michel Pichavant

2/25/2010 10:33:00 AM

0

Michael Rudolf wrote:
> 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
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

2/25/2010 10:59:00 AM

0

Jean-Michel Pichavant wrote:
> Michael Rudolf wrote:
>> 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
> 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

2/25/2010 1:44:00 PM

0

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