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 generally considered to be the pythonic idiom for what you describe.
Cheers,
Daniel
--
Psss, psss, put it down! - http://www.cafepress.com/putitdown
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
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
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/
JM
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 can do, see packages such as PEAK rules. They offer not only
type-based overloading, but also value-based.
Diez
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
JM
: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
> 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.
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