Signature-based Function Overloading in Python

M

Michael Rudolf

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:
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:
if x is None:
pass
else:
pass

?

Thanks,
Michael
 
D

Daniel Fetchinson

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

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:

if x is None:
pass
else:
pass

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

Cheers,
Daniel
 
J

John Posner

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:

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:

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
 
A

Arnaud Delobelle

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

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:

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/Overload3K/
 
L

Lie Ryan

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:
So - What would be the most pythonic way to emulate this?
Is there any better Idom than:

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

Jean-Michel Pichavant

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

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:

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
 
M

Michael Rudolf

First: Thanks for all the replies so far, they really helped me.

Am 24.02.2010 11:28, schrieb Jean-Michel Pichavant:
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
 
D

Diez B. Roggisch

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:

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
 
J

Jean-Michel Pichavant

Michael said:
First: Thanks for all the replies so far, they really helped me.

Am 24.02.2010 11:28, schrieb Jean-Michel Pichavant:

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
 
J

Jean-Michel Pichavant

Jean-Michel Pichavant said:
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
 
M

Michael Rudolf

Am 25.02.2010 11:58, schrieb Jean-Michel Pichavant:
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
 
B

Bruno Desthuilliers

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

Michael Rudolf

Am 27.02.2010 10:00, schrieb alex23:
Michael Rudolf said:
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


Nice!
I really liked
http://bob.pythonmac.org/archives/2005/03/30/five-minute-multimethods-in-python-using-dispatch/
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top